import { CharacterMetadata, ContentBlock, ContentState, DraftDecoratorType, DraftInlineStyle, EditorState, Modifier, RawDraftInlineStyleRange, SelectionState, convertFromRaw, convertToRaw } from 'draft-js';
import { ColSpanInfo, CustomEntityType, DeviceAttributeType, DeviceDescriptionSlice, DeviceEntityRange, DocConfig, DocInstance, EditorBlockParagraphType, EntityExtraData, ExcelCellData, InlineContentSlice, PlanningBasisGroupType, PlanningBasisType, ProtectlandBaseInfoType, RawContent, RowSpanInfo, SpeciesInfoType, TopicDeviceParagraph, TopicTitleTagStatusConfig, TopicType, WordParagraphBlock, WordParagraphBlockSlice, WordParagraphStyle, WordParagraphType } from "../../../utils/types";
import { addTreePropertyForList, deepCopy, defaultProjectSubTableList, dfsRecursive, filterTree, findHalfCheckedKeys, generateTreeData, getCurrentDateNs, getUuid, insertArrayAtPosition, isEmpty, parsePrice, protectlandProblemTableData, provinceList, toastShort, tree2List } from '../../../utils';
import { List } from 'immutable';
import { DraftBlockData, TypeMergeCellBound, TableDataCell } from '../../../types';
import _ from 'lodash';
import { initExcelBuninessContentForWorker } from '../../../utils/workerUtils';
import { initMergeCellBoundGroup } from '../excel-editor/initData';
import { initTableHeader } from '../excel-editor/initData';
import { convertNewTableDataToGridTableData } from '../excel-editor/ExcelEditorHelper';

const protectlandLevelList = [
    { value: '1', label: '国家级' },
    { value: '2', label: '省（自治区、直辖市）级' },
    { value: '3', label: '市（自治州）级' },
    { value: '4', label: '县（自治县、旗、县级市）级' },
]

const proteclandTypeOnlineData = [
    {
        "label": "国家公园",
        "value": "6424f5e8019ebb24cd3d9e7c",
        "children": [
            {
                "label": "生态系统保护",
                "value": "6424f5e8019ebb24cd3d9e7c"
            },
            {
                "label": "野生动植物",
                "value": "6424f601019ebb24cd3d9e8c"
            },
            {
                "label": "自然景观",
                "value": "6424f60b019ebb24cd3d9e95"
            },
            {
                "label": "地质遗迹",
                "value": "6424f617019ebb24cd3d9e9e"
            }
        ]
    },
    {
        "label": "自然保护区",
        "value": "6424f622019ebb24cd3d9ea7",
        "children": [
            {
                "label": "森林生态系统",
                "value": "6424f622019ebb24cd3d9ea7"
            },
            {
                "label": "草原生态系统",
                "value": "6424f62d019ebb24cd3d9eb0"
            },
            {
                "label": "荒漠生态系统",
                "value": "6424f642019ebb24cd3d9eb9"
            },
            {
                "label": "湿地生态系统",
                "value": "6424f653019ebb24cd3d9ec2"
            },
            {
                "label": "海洋生态系统",
                "value": "6424f65d019ebb24cd3d9ecb"
            },
            {
                "label": "动植物保护类",
                "value": "6424f668019ebb24cd3d9ed4"
            },
            {
                "label": "地质遗迹类",
                "value": "6424f672019ebb24cd3d9edd"
            },
            {
                "label": "古生物遗迹类",
                "value": "6424f680019ebb24cd3d9ee6"
            }
        ]
    },
    {
        "label": "自然公园",
        "value": "6424f68c019ebb24cd3d9eef",
        "children": [
            {
                "label": "森林公园",
                "value": "6424f68c019ebb24cd3d9eef"
            },
            {
                "label": "地质公园",
                "value": "6424f697019ebb24cd3d9ef8"
            },
            {
                "label": "湿地公园",
                "value": "6424f6a5019ebb24cd3d9f01"
            },
            {
                "label": "草原公园",
                "value": "6424f6c0019ebb24cd3d9f0e"
            },
            {
                "label": "海洋公园",
                "value": "6424f70f019ebb24cd3d9f1a"
            },
            {
                "label": "沙漠公园",
                "value": "6424f725019ebb24cd3d9f23"
            },
            {
                "label": "风景名胜区",
                "value": "6424f737019ebb24cd3d9f2c"
            }
        ]
    }
]

const adaptProtectlandLevel = (level) => {
    const protectlandLevel = protectlandLevelList.find(ele => {
        return ele.value == level;
    })
    return protectlandLevel ? protectlandLevel.label : '未知等级'
}


const replaceDocInfo = (originText: string, comDocInstance: DocInstance): string => {
    const {
        protectland: {
            type,
            subType,
        },
        protectlandBaseInfo: {
            protectlandArea,
            protectlandAreaUnit = '公顷',
            protectlandLevel,
            protectlandName,
            protectlandProvince,
            protectlandTypeId,
            startYear,
            endYear
        }
    } = comDocInstance;
    let _protectlandAreaUnit = protectlandAreaUnit;
    _protectlandAreaUnit = _protectlandAreaUnit.replace("km2", "km²")
    if (isEmpty(_protectlandAreaUnit)) {
        _protectlandAreaUnit = '公顷';
    }
    let nameReg1 = /\[name\]/gi;
    // let nameReg2 = /\[\*\]/g;
    let areaRg1 = /\[area公顷\]/gi;
    let areaRg2 = /\[area\]/gi;
    let startYearReg1 = /YS\+1/gi;
    let startYearReg2 = /YS\+2/gi;
    let startYearReg3 = /YS\+3/gi;
    let startYearReg4 = /YS\+4/gi;
    let startYearReg5 = /YS\+5/gi;
    let startYearReg = /YS/gi;
    // let startYearReg6 = /YS/gi;
    // let startYearReg7 = /YS/gi;
    // let startYearReg8 = /YS/gi;
    // let startYearReg9 = /YS/gi;
    // let startYearReg10 = /YS/gi;
    // let startYearRegDiff = /YS/gi;
    let endYearReg1 = /YF\+1/gi;
    let endYearReg2 = /YF\+2/gi;
    let endYearReg3 = /YF\+3/gi;
    let endYearReg4 = /YF\+4/gi;
    let endYearReg5 = /YF\+5/gi;
    let endYearReg = /YF/gi;
    originText = originText.replace(nameReg1, protectlandName);
    // originText = originText.replace(nameReg2, protectlandName);
    originText = originText.replace(areaRg1, protectlandArea + _protectlandAreaUnit);
    originText = originText.replace(areaRg2, protectlandArea + _protectlandAreaUnit);
    let provinceReg = /\[p\]/gi;
    // let protectlandNameReg = /\[\*\]/g;
    const findProtectlandProvince = provinceList.find(ele => {
        return ele.label == protectlandProvince;
    });
    const provinceSuffix = findProtectlandProvince ? findProtectlandProvince.suffix : ''
    originText = originText.replace(provinceReg, protectlandProvince ? protectlandProvince + provinceSuffix : '【地理信息缺失】');
    let protectlandTypeReg1 = /\[type\]/gi;
    let protectlandTypeReg2 = /\[\*\]/g;
    originText = originText.replace(protectlandTypeReg1, type ? `“${subType}”类型的${adaptProtectlandLevel(protectlandLevel)}${type}` : '【地理信息缺失】');
    originText = originText.replace(protectlandTypeReg2, type ? getprotectlandTypeReg2(type, subType) : '');
    // originText = originText.replace(protectlandNameReg, protectlandName);

    originText = originText.replace(startYearReg1, (new Date(startYear).getFullYear() + 1) + '');
    originText = originText.replace(startYearReg2, (new Date(startYear).getFullYear() + 2) + '');
    originText = originText.replace(startYearReg3, (new Date(startYear).getFullYear() + 3) + '');
    originText = originText.replace(startYearReg4, (new Date(startYear).getFullYear() + 4) + '');
    originText = originText.replace(startYearReg5, (new Date(startYear).getFullYear() + 5) + '');
    originText = originText.replace(startYearReg, new Date(startYear).getFullYear() + '');

    originText = originText.replace(endYearReg1, (new Date(endYear).getFullYear() + 1) + '');
    originText = originText.replace(endYearReg2, (new Date(endYear).getFullYear() + 2) + '');
    originText = originText.replace(endYearReg3, (new Date(endYear).getFullYear() + 3) + '');
    originText = originText.replace(endYearReg4, (new Date(endYear).getFullYear() + 4) + '');
    originText = originText.replace(endYearReg5, (new Date(endYear).getFullYear() + 5) + '');
    originText = originText.replace(endYearReg, new Date(endYear).getFullYear() + '');
    originText = originText.replace(/\\n/g, '');
    return originText;
}

const getDeviceTopicReplaceText = (deviceTopic: TopicType, deviceAttributeType: DeviceAttributeType) => {
    let replaceText = '';
    switch (deviceAttributeType) {
        case '$[N]':
            replaceText = deviceTopic.count + '';
            break;
        case '$[S]':
        case '$[X]':
            replaceText = deviceTopic.topicName + '';
            break;
        case '$[U]':
            replaceText = deviceTopic.unit + '';
            break;
        default:
            break;
    }
    return replaceText + "";
}

const getprotectlandTypeReg2 = (type: string, subType) => {
    let str = '';
    switch (type) {
        case '国家公园':
            str = '国家公园'
            break;
        case '自然保护区':
            str = '保护区'
            break;
        case '自然公园':
            switch (subType) {
                case '森林公园':
                    str = '森林公园';
                    break;
                case '地质公园':
                    str = '地质公园';
                    break;
                case '湿地公园':
                    str = '湿地公园';
                    break;
                case '草原公园':
                    str = '草原公园';
                    break;
                case '海洋公园':
                    str = '海洋公园';
                    break;
                case '沙漠公园':
                    str = '沙漠公园';
                    break;
                case '风景名胜区':
                    str = '风景名胜区';
                    break;
                default:
                    break;
            }
            break;
        default:
            str = type;
            break;
    }
    return str;
}


const replaceDeviveInfo = (originText: string, comDocInstance: DocInstance, deviceTopic: TopicType): string => {
    const {
        protectland: {
            type,
            subType
        },
        protectlandBaseInfo: {
            protectlandArea,
            protectlandAreaUnit,
            protectlandLevel,
            protectlandName,
            protectlandProvince,
            protectlandTypeId
        }
    } = comDocInstance;
    let nameReg = /\[name\]/gi;

    originText = originText.replace(nameReg, protectlandName);
    let provinceReg = /\[p\]/gi;
    let protectlandTypeReg1 = /\[type\]/gi;
    let protectlandTypeReg2 = /\[\*\]/g;
    let unitReg = /\$\[U\]/g;
    let countReg = /\$\[N\]/g;
    let unitPriceReg = /\$\[U\]/g;
    let deviceNameReg1 = /\$\[S\]/g;
    let deviceNameReg2 = /\$\[X\]/g;
    originText = originText.replace(provinceReg, protectlandProvince ? protectlandProvince + '省' : '【地理信息缺失】');
    originText = originText.replace(protectlandTypeReg1, type ? `“${subType}”类型的${adaptProtectlandLevel(protectlandLevel)}${type}` : '');
    originText = originText.replace(protectlandTypeReg2, type ? getprotectlandTypeReg2(type, subType) : '');
    // originText = originText.replace(protectlandNameReg, protectlandName);
    originText = originText.replace(/\\n/g, '');
    originText = originText.replace(unitReg, deviceTopic.unit);
    originText = originText.replace(deviceNameReg1, deviceTopic.topicName);
    originText = originText.replace(deviceNameReg2, deviceTopic.topicName);
    originText = originText.replace(countReg, deviceTopic.count);
    return originText;
}

const getEntityText = (matchingCharacter: string, comDocInstance: DocInstance, deviceTopic: TopicType) => {
    const {
        protectland: {
            type,
            subType
        },
        protectlandBaseInfo: {
            protectlandArea,
            protectlandAreaUnit,
            protectlandLevel,
            protectlandName,
            protectlandProvince,
            protectlandTypeId
        }
    } = comDocInstance;
    let entityText: string = "";
    switch (matchingCharacter) {
        //
        case '[*]':
        case '$[*]':
            entityText = getprotectlandTypeReg2(type, subType);
            break;
        case '[NAME]':
        case '$[NAME]':
            entityText = protectlandName;
            break;
        case '[P]':
        case '$[P]':
            entityText = protectlandProvince + '省';
            break;
        case '[type]':
        case '$[type]':
            entityText = `“${subType}”类型的${adaptProtectlandLevel(protectlandLevel)}${type}`;
            break;
        case '$[S]':
        case '$[X]':
            entityText = deviceTopic.topicName;
            break;
        case '$[N]':
            entityText = deviceTopic.count;
            break;
        case '$[U]':
            entityText = deviceTopic.unit;
            break;
        default:
            break;
    }
    return entityText + '';
}

const maptchSplitHighLightTextSlice = (text: string): { inlineStyleList: [], content: string }[] => {
    // let text = "这是一段文本#测试内容#这是文本结尾";
    let regex = /(#([^#]+)#)|([^#]+)/g;
    let result = [];
    let match;
    while ((match = regex.exec(text)) !== null) {
        if (match[1]) {
            result.push({ content: match[2], inlineStyleList: ['inline_background_color-#ffff00', 'normal_inline_style', 'system_highlight_tag'] });
        } else {
            result.push({ content: match[0], inlineStyleList: ['normal_inline_style', 'normal_inline_style'] });
        }
    }
    return result;
}


const moveSelectionToEnd = (editorState: EditorState) => {
    const content = editorState.getCurrentContent();
    const blockMap = content.getBlockMap();
    const key = blockMap.last().getKey();
    const length = blockMap.last().getLength();
    const selection = new SelectionState({
        anchorKey: key,
        anchorOffset: length,
        focusKey: key,
        focusOffset: length,
    });
    return EditorState.acceptSelection(editorState, selection);
};


/**
 * 根据文本大纲下的设施设备，为每一个构造好数据结构
 * 包括：每一个设施设备节点的设施文本、设备背景文本的集合（以便于随机抽取）
 * @param deviceTopicList 
 * @returns 
 */
const getDeviceParagraphListGroup = (deviceTopicList: TopicType[]): TopicDeviceParagraph[] => {
    let deviceParagraphListGroup: TopicDeviceParagraph[] = [];
    let typeS = false;
    let typeX = false;
    deviceTopicList.forEach((deviceTopic, index) => {

        if (deviceTopic.deviceType == 'S') {
            const facilitiesBackgroundParagraphList: string[] = [];  //当前设施的设施文本
            let currentfacilitiesBackgroundParagraph: string = "";   //随机选中的设施的设施文本
            typeS = true;
            //设施文本
            if (!isEmpty(deviceTopic.facilitiesBackgroundParagraph1)) {
                facilitiesBackgroundParagraphList.push(deviceTopic.facilitiesBackgroundParagraph1);
            }
            if (!isEmpty(deviceTopic.facilitiesBackgroundParagraph2)) {
                facilitiesBackgroundParagraphList.push(deviceTopic.facilitiesBackgroundParagraph2);
            }
            if (!isEmpty(deviceTopic.facilitiesBackgroundParagraph3)) {
                facilitiesBackgroundParagraphList.push(deviceTopic.facilitiesBackgroundParagraph3);
            }
            if (!isEmpty(deviceTopic.facilitiesBackgroundParagraph4)) {
                facilitiesBackgroundParagraphList.push(deviceTopic.facilitiesBackgroundParagraph4);
            }
            currentfacilitiesBackgroundParagraph = lotteryStringList(facilitiesBackgroundParagraphList);
            // if (
            //     deviceParagraphListGroup[deviceParagraphListGroup.length - 1] &&
            //     deviceParagraphListGroup[deviceParagraphListGroup.length - 1].deviceGroupType == 'S' &&
            //     (
            //         //如果这是设施、且它的设施文本与最近的一条
            //         deviceParagraphListGroup[deviceParagraphListGroup.length - 1].currentFacilitiesBackgroundParagraph == currentfacilitiesBackgroundParagraph ||
            //         //或者设施文本是空的
            //         isEmpty(currentfacilitiesBackgroundParagraph)
            //     )
            // ) {
            //     deviceParagraphListGroup[deviceParagraphListGroup.length - 1].deviceTopicList.push(deviceTopic);
            // } else {
            //     //推入新的一条数据
            //     deviceParagraphListGroup.push({
            //         deviceGroupType: 'S',
            //         currentFacilitiesBackgroundParagraph: currentfacilitiesBackgroundParagraph,
            //         deviceTopicList: [deviceTopic]
            //     })
            // }
            deviceParagraphListGroup.push({
                deviceGroupType: 'S',
                currentFacilitiesBackgroundParagraph: currentfacilitiesBackgroundParagraph,
                deviceTopicList: [deviceTopic]
            })
        } else {
            const deviceBackgroundParagraphList: string[] = [];      //当前设备的背景文本
            let currentDeviceBackgroundParagraph: string = "";       //随机选中的设备的背景文本
            let deviceConstituteParagraph: string = "";              //设备结构文本
            typeX = true;
            //设备背景文本
            if (!isEmpty(deviceTopic.deviceBackgroundParagraph1)) {
                deviceBackgroundParagraphList.push(deviceTopic.deviceBackgroundParagraph1);
            }
            if (!isEmpty(deviceTopic.deviceBackgroundParagraph2)) {
                deviceBackgroundParagraphList.push(deviceTopic.deviceBackgroundParagraph2);
            }
            if (!isEmpty(deviceTopic.deviceBackgroundParagraph3)) {
                deviceConstituteParagraph = deviceTopic.deviceBackgroundParagraph3;
            }
            currentDeviceBackgroundParagraph = lotteryStringList(deviceBackgroundParagraphList);
            if (

                deviceParagraphListGroup[deviceParagraphListGroup.length - 1] &&
                deviceParagraphListGroup[deviceParagraphListGroup.length - 1].deviceGroupType == 'X' &&
                (
                    //如果这是设施、且它的设施文本与最近的一条
                    deviceParagraphListGroup[deviceParagraphListGroup.length - 1].currentDeviceBackgroundParagraph == currentDeviceBackgroundParagraph ||
                    //或者设备问题是空的
                    isEmpty(currentDeviceBackgroundParagraph)
                )
            ) {
                deviceParagraphListGroup[deviceParagraphListGroup.length - 1].deviceTopicList.push(deviceTopic);
            } else {
                //推入新的一条数据
                deviceParagraphListGroup.push({
                    deviceGroupType: 'X',
                    currentDeviceBackgroundParagraph: currentDeviceBackgroundParagraph,
                    deviceTopicList: [deviceTopic]
                })
            }
        }
    })
    return deviceParagraphListGroup;
}

const generateDeviceParagraphSlice = (deviceParagraph: string): string[] => {
    // const pattern = /(\$?\[[^\]]+\])/;
    const pattern = /(\$?\[[^\]]+\]|YS\+?[1-5]?|YF\+?[1-5]?|YF-YS\+1)/;  //|YF-YS\+1
    const deviceParagraphSlice: string[] = deviceParagraph.split(pattern).filter((item) => item);
    return deviceParagraphSlice;
}

/**
 * 随机抽取
 * @param paragraphList 
 * @returns 
 */
const lotteryStringList = (paragraphList: string[]): string => {
    const len = paragraphList.length;
    if (len == 0) {
        return '';
    }
    const randomIndex = Math.floor(Math.random() * len);
    return paragraphList[randomIndex];
}

const checkIsParagraphTitle = (currentBlockText: string) => {
    const regex = /^(第\s*\d+\s*章\s|\d+(\.\d+){0,3}(\s))/;
    return currentBlockText.match(regex);
}

const getInlineStyleRangesForBlock = (block) => {
    const inlineStyleRanges = [];

    const processStyledCharacter = (start, end) => {
        const charMetadata = block.getCharacterList().get(start);
        const charStyle = charMetadata.getStyle();

        if (!charStyle.isEmpty()) {
            charStyle.forEach(styleName => {
                inlineStyleRanges.push({
                    offset: start,
                    length: end - start,
                    style: styleName,
                });
            });
        }
    };

    block.findStyleRanges(
        (charMetadata) => !charMetadata.getStyle().isEmpty(),
        processStyledCharacter
    );

    return inlineStyleRanges;
}


const getDeviceParagraphSpecialTextEntities = (block: ContentBlock, contentState: ContentState) => {
    const text = block.getText();
    const entityDataList = [];
    let entityKey = '';
    let startOffset = 0;
    // 遍历文本以查找商品价格实体
    for (let i = 0; i < text.length; i++) {
        const currentEntityKey = block.getEntityAt(i);

        if (currentEntityKey) {
            const currentEntity = contentState.getEntity(currentEntityKey);

            if (currentEntity.getType() === 'SPECIAL_TEXT') {
                if (!entityKey) {
                    entityKey = currentEntityKey;
                    startOffset = i;
                } else if (currentEntityKey !== entityKey) {
                    // 当前实体与前一个实体不同时，保存前一个实体的数据
                    const previousEntity = contentState.getEntity(entityKey);
                    entityDataList.push({
                        entityKey,
                        entity: previousEntity,
                        data: previousEntity.getData(),
                        offset: startOffset,
                        length: i - startOffset,
                    });
                    // 更新实体键和开始偏移量
                    entityKey = currentEntityKey;
                    startOffset = i;
                }
            } else {
                // 如果当前实体类型不匹配，则重置实体键
                entityKey = null;
            }
        } else {
            if (entityKey) {
                // 遇到不是实体的字符时，保存已找到的实体数据
                const entity = contentState.getEntity(entityKey);
                entityDataList.push({
                    entityKey,
                    entity: entity,
                    data: entity.getData(),
                    offset: startOffset,
                    length: i - startOffset,
                });
                entityKey = null;
            }
        }
    }

    // 处理最后一个实体（如果有）
    if (entityKey) {
        const entity = contentState.getEntity(entityKey);
        entityDataList.push({
            entityKey,
            entity: entity,
            data: entity.getData(),
            offset: startOffset,
            length: text.length - startOffset,
        });
    }

    return entityDataList;
};


const updateEditorState = (editorState, newContentState, selectionState) => {
    return EditorState.set(editorState, {
        currentContent: newContentState,
        selection: selectionState,
        // 在输入中文时，将 nativelyRenderedContent 设置为 null，以阻止重新渲染
        nativelyRenderedContent: null,
    });
}

const getDeviceEntityTag = (deviceEntityRange: DeviceEntityRange): string => {
    return deviceEntityRange.deviceTopicId + deviceEntityRange.deviceAttributeType;
}

const getTwoTextDiffLen = (text1: string, text2: string): number => {
    return (text1 + '').length - (text2 + '').length;
}


/**
 * 
 * @param inputStr 
 * @param replaceTextSlice 
 * @param startIndex 
 * @param endIndex 
 */
const replaceTextByRange = (
    inputStr: string,
    oldTextSlice: string,
    replaceTextSlice: string,
    startIndex: number,
    endIndex: number
) => {
    try {
        if (isEmpty(startIndex) || isEmpty(endIndex) || startIndex >= endIndex) {
            return inputStr;
        }
        const targetStr = inputStr.substring(startIndex, endIndex);
        const replacedStr = targetStr.replace(oldTextSlice, replaceTextSlice);
        const result = inputStr.slice(0, startIndex) + replacedStr + inputStr.slice(endIndex);
        return result;
    } catch (e) {
        return inputStr;
    }
}

/**
 * 
 * @param deviceTopicList 这一段deviceEnity组合文本中，可能涉及到的设施设备节点
 * @param deviceEntityList  deviceEntity集合
 * @param deviceBackgroundParagraphText entity组合的背景文本
 * @returns 
 */
const preCorrectionTopicChildDeviceEntityList = (
    deviceTopicList: TopicType[],
    deviceEntityList: DeviceEntityRange[],
    deviceBackgroundParagraphText: string
): {
    entityRangesChanged: boolean
    newDeviceEntityList: DeviceEntityRange[],
    newDeviceBackgroundParagraphText: string
} => {
    let totalDiffOffsetLength = 0;
    let replacedDeviceBackgroundParagraphText = deviceBackgroundParagraphText;
    let entityRangesChanged = false;
    let totalDiffTextLength = 0;
    deviceEntityList.forEach((oldDeviceEntity, oldDeviceEntityIndex) => {
        const findCurrentDeviceTopic = deviceTopicList.find(deviceTopic => {
            return deviceTopic.id == oldDeviceEntity.deviceTopicId;
        });
        const replacedText = getDeviceTopicReplaceText(findCurrentDeviceTopic, oldDeviceEntity.deviceAttributeType);
        if (isEmpty(oldDeviceEntity.start)) {
            oldDeviceEntity.start = oldDeviceEntity.textOffset
        }
        if (isEmpty(oldDeviceEntity.end)) {
            oldDeviceEntity.end = oldDeviceEntity.start + (oldDeviceEntity.text + '').length;
        }
        if (replacedText != oldDeviceEntity.text) {
            entityRangesChanged = true;
            oldDeviceEntity.start = oldDeviceEntity.start + totalDiffOffsetLength;
            let tempDiffOffsetLength = getTwoTextDiffLen(replacedText, oldDeviceEntity.text);
            // const findEntityNewEnd = oldDeviceEntity.start + replacedText.length;
            // let tempDiffOffsetLength = findEntityNewEnd - oldDeviceEntity.end;
            oldDeviceEntity.text = replacedText;
            oldDeviceEntity.diffOffsetLength = tempDiffOffsetLength;
            oldDeviceEntity.textOffset = oldDeviceEntity.start;
            oldDeviceEntity.textLength = oldDeviceEntity.text.length;
            oldDeviceEntity.end = oldDeviceEntity.start + + replacedText.length;
            totalDiffOffsetLength += oldDeviceEntity.diffOffsetLength;
        } else {
            oldDeviceEntity.start = oldDeviceEntity.start + totalDiffOffsetLength;
            oldDeviceEntity.end = oldDeviceEntity.end + totalDiffOffsetLength;
            oldDeviceEntity.textOffset = oldDeviceEntity.start;
            oldDeviceEntity.textLength = oldDeviceEntity.text.length;
        }
    })
    let blockText = deviceBackgroundParagraphText;
    deviceEntityList.forEach((optionEntityRange, optionEntityRangeIndex) => {
        //第一步：根据optionEntityRange的属性变化，来更新blockText
        if (optionEntityRange.diffOffsetLength) {
            const blockTextBeforeSlice = blockText.substring(0, optionEntityRange.start);
            const blockTextAfterSlice = blockText.slice(optionEntityRange.end - optionEntityRange.diffOffsetLength);
            blockText = blockTextBeforeSlice + optionEntityRange.text + blockTextAfterSlice;
        }
    })
    replacedDeviceBackgroundParagraphText = blockText;
    return {
        entityRangesChanged,
        newDeviceEntityList: deviceEntityList,
        newDeviceBackgroundParagraphText: replacedDeviceBackgroundParagraphText
    };
}

const createContentBlock = (text: string, blockType, blockKey, inlineStyleTypeList: string[]) => {
    let inlineStyleRanges = [];
    inlineStyleTypeList.forEach(inlineStyle => {
        inlineStyleRanges.push({
            style: inlineStyle,
            offset: 0,
            length: text ? text.length : 0,
        })
    })
    return {
        key: blockKey,
        text,
        type: blockType,
        inlineStyleRanges,
        entityRanges: [],
        data: {},
    }
}

/**
 * @param inlineContentList 
 * @param blockType 
 * @param blockKey 
 * @returns 
*/
const createContentBlockByInlineRanges = (
    inlineContentList: { content: string, inlineStyleList: string[] }[],
    blockType: string,
    blockKey: string,
) => {
    let inlineStyleRanges = [];
    let offset = 0;
    let totalText = "";
    inlineContentList.forEach(inlineContent => {
        inlineContent.inlineStyleList.forEach(inlineStyle => {
            inlineStyleRanges.push({
                style: inlineStyle,
                offset: offset,
                length: inlineContent.content.length
            })
        })
        inlineStyleRanges.push({
            style: 'normal_inline_style',
            offset: offset,
            length: inlineContent.content.length
        })
        totalText += inlineContent.content;
        offset = offset + inlineContent.content.length;
    })
    let result = {
        key: blockKey,
        text: totalText,
        type: blockType,
        inlineStyleRanges,
        entityRanges: [],
        data: {},
    }
    return result;
}

const adaptWordTitleByTextTopic = (textTopic: TopicType) => {
    try {
        const serialNumber = textTopic.serialNumber;
        let titleText = ''
        switch (textTopic.topicLevel) {
            case '1':
                titleText = `第 ${serialNumber} 章  ${textTopic.topicName}`
                break;
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
                titleText = `${serialNumber} ${textTopic.topicName}`;
                break;
            default:
                titleText = `${serialNumber} ${textTopic.topicName}`;
                break;
        }
        return titleText;
    } catch (e) {
        return textTopic.topicName;
    }
}

// function filterChecked(tree) {
//     let result = [];

//     function traverse(node) {
//         let hasCheckedChild = false;

//         if (node.children) {
//             for (let child of node.children) {
//                 if (traverse(child)) {
//                     hasCheckedChild = true;
//                 }
//             }
//         }

//         // 如果节点自身为选中状态，或者其子节点中有至少一个是选中状态
//         if (node.checked || hasCheckedChild) {
//             // 为了防止修改原数据，复制一份当前节点
//             let newNode = {...node};
//             // 清除子节点，因为我们会添加新的满足条件的子节点
//             newNode.children = [];

//             if (node.children) {
//                 // 对于当前节点的每一个子节点，如果子节点自身被选中，或者其子节点中有被选中的，那么该子节点满足条件
//                 for (let child of node.children) {
//                     if (child.checked || child.children?.some(subChild => subChild.checked)) {
//                         newNode.children.push(child);
//                     }
//                 }
//             }

//             result.push(newNode);

//             // 返回true表示当前节点或者其子节点中至少有一个节点是选中状态
//             return true;
//         } else {
//             // 否则返回false表示当前节点和其所有子节点都没有被选中
//             return false;
//         }
//     }

//     traverse({children: tree});  // 用一个虚假的根节点来启动遍历
//     return result;
// }


/**
 * 更新规划实例前，预处理topicList
 * @param topicList 
 */
const preProcessComDocInstanceBeforeUpdate = (
    newComDocInstance: DocInstance,
    newComDocConfig: DocConfig,
): DocInstance => {
    try {
        let _tempTopicList = newComDocInstance.topicList
        let _tempTopicTreeData = generateTreeData(addTreePropertyForList(_tempTopicList));
        let serialNumberList = [];
        let topicTitleTagStatusConfig: TopicTitleTagStatusConfig = {
            PlanningYears: false,
            EcologicalBenefitAnalysis: false,
            SocialBenefitAnalysis: false,
            SubSocialBenefitAnalysis: false,
            EconomicBenefitAnalysis: false,
            EnvironmentalCapacityAnalysis: false,
            OverallGoal: false,
            ShortTermGoal: false,
            MediumAndLongTermGoals: false,
            MainProject: false,
            ExistingProblems: false,
            MainContentsOfPlanning: false,
            InvestmentPlan: false,
            PlanningInvestment: false,
        }
        let mainContentsOfThePlanningActive = false;  //规划主要建设内容
        let planningGoalActive = false;               //规划目标
        let keyConstructionProjectActive = false;     //重点建设工程
        dfsRecursive(_tempTopicTreeData, (topic: TopicType, level: number) => {
            if (serialNumberList.length > level) {
                serialNumberList = serialNumberList.splice(0, level + 1)
                serialNumberList[serialNumberList.length - 1]++;
            } else if (serialNumberList.length == level) {
                if (isEmpty(serialNumberList[level])) {
                    serialNumberList[level] = 1;
                } else {
                    serialNumberList[level]++;
                }
            } else {
                serialNumberList.push(1)
            }
            const serialNumber = serialNumberList.join('.');
            topic.serialNumber = serialNumber;
            let topicWordParagraphList = topic.wordParagraphList;
            //开始检查topic基本属性变化（是否牵扯到文本编辑器的配置更新的，暂时只有节点名称）
            const findTopicTitleParagraphBlock = topicWordParagraphList && topicWordParagraphList.find(wordParagraph => {
                return wordParagraph && wordParagraph.paragraphType == 'topic_title';
            })
            //这个其实没有用的
            let tempNextEnitityKey = 0;
            if (topic.topicType === 'text') {
                const newTextTopicTitle = adaptWordTitleByTextTopic(topic);
                const originTopicWordParagraphList = topic.wordParagraphList ? [...topic.wordParagraphList] : [];
                if (findTopicTitleParagraphBlock) {
                    if (findTopicTitleParagraphBlock.text !== newTextTopicTitle) {
                        findTopicTitleParagraphBlock.text = newTextTopicTitle;
                        let inlineStyleRanges = [];
                        if (topic.topicLevel == '1' || topic.topicLevel == '2' || topic.topicLevel == '3') {
                            inlineStyleRanges = [
                                { length: findTopicTitleParagraphBlock.text.length, offset: 0, style: 'BOLD' },
                                { length: findTopicTitleParagraphBlock.text.length, offset: 0, style: 'HeiTi' },
                            ];
                        } else {
                            inlineStyleRanges = [
                                { length: findTopicTitleParagraphBlock.text.length, offset: 0, style: 'BOLD' },
                                { length: findTopicTitleParagraphBlock.text.length, offset: 0, style: 'SongTi' },
                            ];
                        }
                        findTopicTitleParagraphBlock.inlineStyleRanges = inlineStyleRanges;
                    } else {
                    }
                } else {
                    //重置自定义大纲标题文本
                    const newTextTopicTitle = adaptWordTitleByTextTopic(topic);
                    //@ts-ignore
                    topic.topicLevel = topic.topicLevel + '';
                    let topicTitleParagraphBlock: WordParagraphBlock = {
                        type: 'text',
                        text: newTextTopicTitle,
                        textTopicId: topic.id,
                        blockId: generateBlockId(),
                        paragraphStyle: getTopicTitleParagraphStyle(topic),
                        paragraphType: 'topic_title'
                    };
                    let inlineStyleRanges = [];
                    if (topic.topicLevel == '1' || topic.topicLevel == '2' || topic.topicLevel == '3') {
                        inlineStyleRanges = [
                            { length: topicTitleParagraphBlock.text.length, offset: 0, style: 'BOLD' },
                            { length: topicTitleParagraphBlock.text.length, offset: 0, style: 'HeiTi' },
                        ];
                    } else {
                        inlineStyleRanges = [
                            { length: topicTitleParagraphBlock.text.length, offset: 0, style: 'BOLD' },
                            { length: topicTitleParagraphBlock.text.length, offset: 0, style: 'SongTi' },
                        ];
                    }
                    topicTitleParagraphBlock.inlineStyleRanges = inlineStyleRanges;
                    topicWordParagraphList = [topicTitleParagraphBlock];
                    topic.wordParagraphList = topicWordParagraphList;
                }
                const {
                    newTopic,
                    newTopicWordParagraphList,
                    _mainContentsOfThePlanningActive,
                    _planningGoalActive
                } = generateSystemChapter(
                    topic,
                    _tempTopicTreeData,
                    topicTitleTagStatusConfig,
                    newComDocInstance,
                    newComDocConfig,
                    topicWordParagraphList,
                    mainContentsOfThePlanningActive,
                    planningGoalActive
                );
                if (topic.topicName === '规划投资') {
                }
                topic.wordParagraphList = [...topicWordParagraphList];
                topicWordParagraphList = newTopicWordParagraphList;
                topic = { ...newTopic };
                mainContentsOfThePlanningActive = _mainContentsOfThePlanningActive;
                planningGoalActive = _planningGoalActive;

                let childrenDeviceTopicList: TopicType[] = [];
                if (topic.children && topic.children.length) {
                    childrenDeviceTopicList = topic.children.filter(_topic => {
                        return _topic.topicType == 'device' && _topic.checked;
                    })
                }
                if (
                    topic.childrenDeviceTopicListLength != undefined &&
                    childrenDeviceTopicList.length !== topic.childrenDeviceTopicListLength
                ) {
                    //如果这个文本节点下的entity数量有变化
                    topic.childrenDeviceTopicListLength = childrenDeviceTopicList.length;
                    const {
                        deviceParagraphBlockList,
                        newNextEntityKey
                    } = getDeviceParagraphBlockList(topic, childrenDeviceTopicList, tempNextEnitityKey, newComDocInstance, 'preProcessComDocInstanceBeforeUpdate');
                    if (deviceParagraphBlockList && deviceParagraphBlockList.length) {
                        tempNextEnitityKey = newNextEntityKey;
                        let originWordParagraphList = topic.wordParagraphList;
                        let deviceWordParagraphStartIndex = -1;
                        for (let i = 0; i < originWordParagraphList.length; i++) {
                            if (originWordParagraphList[i].paragraphType == 'device_background_paragraph') {
                                originWordParagraphList.splice(i, 1);
                                if (deviceWordParagraphStartIndex == -1) {
                                    deviceWordParagraphStartIndex = i;
                                }
                                i--;
                            }
                        }
                        let newWordParagraphList = originWordParagraphList;
                        if (deviceWordParagraphStartIndex == -1) {
                            newWordParagraphList = originWordParagraphList.concat(deviceParagraphBlockList);
                        } else {
                            newWordParagraphList = insertArrayAtPosition(originWordParagraphList, deviceParagraphBlockList, deviceWordParagraphStartIndex);
                        }
                        topic.wordParagraphList = newWordParagraphList;
                        const findTopic = _tempTopicList.find(_topic => {
                            return _topic.id == topic.id;
                        })
                        if (findTopic) {
                            findTopic.wordParagraphList = [...newWordParagraphList]
                        }
                    } else {
                    }
                } else {
                    if (childrenDeviceTopicList.length) {
                        const findDeviceWordParagraphBlock = topicWordParagraphList.find(paragraphBlock => {
                            return paragraphBlock && paragraphBlock.paragraphType == 'device_background_paragraph';
                        })
                        if (findDeviceWordParagraphBlock) {
                            const {
                                entityRanges,
                                text
                            } = findDeviceWordParagraphBlock;
                            const {
                                entityRangesChanged,
                                newDeviceEntityList,
                                newDeviceBackgroundParagraphText,
                            } = preCorrectionTopicChildDeviceEntityList(childrenDeviceTopicList, entityRanges, text);
                            if (entityRangesChanged) {
                                // findDeviceWordParagraphBlock.text = text;
                                // findDeviceWordParagraphBlock.entityRanges = entityRanges;
                                findDeviceWordParagraphBlock.text = newDeviceBackgroundParagraphText;
                                findDeviceWordParagraphBlock.entityRanges = newDeviceEntityList;
                            }
                        }
                    }
                    // topic.wordParagraphList = topicWordParagraphList;
                }
                topic.wordParagraphList = topicWordParagraphList;
            }
        })
        newComDocInstance.topicList = [..._tempTopicList];
        return newComDocInstance;
    } catch (e) {
    }
}


const filterChecked = (tree) => {
    return tree
        .filter(node => node.checked || (node.children && hasChecked(node.children)))
        .map(node => {
            if (node.children) {
                return { ...node, children: filterChecked(node.children) };
            } else {
                return node;
            }
        });
}

function hasChecked(tree) {
    return tree.some(node => node.checked || (node.children && hasChecked(node.children)));
}

/**
 * 根据已经初始化过的文档，生成rawContent
 * @param newComDocInstance 
 * @returns 组装好的rawContent
 */
const getInitializedRawContent = (newComDocInstance: DocInstance, newComDocConfig: DocConfig): { updatedComDocInstance: DocInstance, rawContent: RawContent } => {
    const _tempTopicList = deepCopy(newComDocInstance.topicList);
    const checkedKeys = [];
    _tempTopicList.forEach(ele => {
        if (ele.checked) {
            checkedKeys.push(ele.id)
        }
    })
    const halfCheckeNodeList: string[] = findHalfCheckedKeys(_tempTopicList, checkedKeys);
    _tempTopicList.forEach(ele => {
        if (halfCheckeNodeList.includes(ele.id)) {
            ele.checked = true;
        }
    })
    const tempTopicTreeData = generateTreeData(addTreePropertyForList(_tempTopicList));
    const realUseTopciTreeData = filterChecked(tempTopicTreeData)
    const rawContent = {
        blocks: [
        ],
        entityMap: {}
    }
    let serialNumberList = [];
    let nextEntityKey = 0;
    dfsRecursive(realUseTopciTreeData, (topic: TopicType, level: number) => {
        let topicTitleTagStatusConfig: TopicTitleTagStatusConfig = {
            PlanningYears: false,
            EcologicalBenefitAnalysis: false,
            SocialBenefitAnalysis: false,
            SubSocialBenefitAnalysis: false,
            EconomicBenefitAnalysis: false,
            EnvironmentalCapacityAnalysis: false,
            OverallGoal: false,
            ShortTermGoal: false,
            MediumAndLongTermGoals: false,
            MainProject: false,
            ExistingProblems: false,
            MainContentsOfPlanning: false,
            InvestmentPlan: false,
            PlanningInvestment: false,
        }
        let mainContentsOfThePlanningActive = false;  //规划主要建设内容
        let planningGoalActive = false;               //规划目标
        let keyConstructionProjectActive = false;     //重点建设工程
        let wordParagraphList = [];
        topic.wordParagraphList && topic.wordParagraphList.forEach(ele => {
            if (ele && ele.blockId) {
                wordParagraphList.push(ele)
            }
        });
        let topicWordParagraphList: WordParagraphBlock[] = wordParagraphList ? wordParagraphList : [];
        const {
            newTopic,
            newTopicWordParagraphList,
            _mainContentsOfThePlanningActive,
            _planningGoalActive
        } = generateSystemChapter(
            topic,
            tempTopicTreeData,
            topicTitleTagStatusConfig,
            newComDocInstance,
            newComDocConfig,
            topicWordParagraphList,
            mainContentsOfThePlanningActive,
            planningGoalActive
        );
        if (newTopicWordParagraphList && newTopicWordParagraphList.length) {
            wordParagraphList = [...newTopicWordParagraphList];
            topicWordParagraphList = [...newTopicWordParagraphList];
        }
        //生成的topic
        if (serialNumberList.length > level) {
            serialNumberList = serialNumberList.splice(0, level + 1)
            serialNumberList[serialNumberList.length - 1]++;
        } else if (serialNumberList.length == level) {
            if (isEmpty(serialNumberList[level])) {
                serialNumberList[level] = 1;
            } else {
                serialNumberList[level]++;
            }
        } else {
            serialNumberList.push(1)
        }
        const serialNumber = serialNumberList.join('.');
        topic.serialNumber = serialNumber;
        if (isEmpty(topic.wordParagraphList)) {
            topic.wordParagraphList = []
        }
        if (wordParagraphList && wordParagraphList.length) {
            wordParagraphList.forEach((worParagraph, worParagraphIndex) => {
                if (worParagraphIndex === 0) {
                    worParagraph = getWordParagraphTitle(topic, wordParagraphList);
                }
                const tempContentBlock = convertWordParagraphToContentBlock(worParagraph);
                rawContent.blocks.push(tempContentBlock);
                if (worParagraph.entityRanges && worParagraph.entityRanges.length) {
                    worParagraph.entityRanges.forEach(entityRange => {
                        rawContent.entityMap[nextEntityKey] = {
                            type: 'SPECIAL_TEXT',
                            mutability: 'IMMUTABLE',
                            data: entityRange,
                        };
                        //这里必须更新，为了能够实现勾选联动
                        entityRange.key = nextEntityKey
                        nextEntityKey++;
                    })
                    worParagraph.entityRanges.forEach(entityRange => {
                        rawContent.blocks[rawContent.blocks.length - 1].entityRanges.push({
                            key: entityRange.key,
                            offset: entityRange.textOffset,
                            length: entityRange.textLength,
                        });
                    })
                }
            })
        }
    })
    return {
        rawContent,
        updatedComDocInstance: newComDocInstance
    };
}

const generatePlanningYearsTopic = (topic: TopicType, comDocInstance: DocInstance): string => {
    const {
        protectland: {
            type,
            subType,
        },
        protectlandBaseInfo: {
            protectlandArea,
            protectlandAreaUnit = '公顷',
            protectlandLevel,
            protectlandName,
            protectlandProvince,
            protectlandTypeId,
            startYear,
            endYear
        }
    } = comDocInstance;
    if (startYear && endYear) {
        const startYearStr = new Date(startYear).getFullYear();
        const endYearStr = new Date(endYear).getFullYear();
        let newTopicName = `规划期限（${startYearStr}年—${endYearStr}年）`;
        const yearLen = Number(endYearStr) - Number(startYearStr) + 1;
        const centerYearStr = (((Number(endYearStr) - Number(startYearStr)) / 2) + Number(startYearStr)).toFixed(0);
        let yearRange1 = `${startYearStr}年—${centerYearStr}年`;
        let yearRange2 = `${Number(centerYearStr) + 1}年—${endYearStr}年`;
        let topicBackgroundPargraphText = `根据保护区建设发展的现实需要，按照规划原则，确定${protectlandName}总体规划的期限为${yearLen}年，即${startYearStr}年—${endYearStr}年。分两期：其中，近期：${yearRange1}；远期：${yearRange2}。`
        return topicBackgroundPargraphText;
    }
    return '';
}

const generateBlockId = () => {
    return getUuid(8).toLowerCase() + getCurrentDateNs() + '_block'
}

const adaptWordParagraphTypeToBlockType = (wordParagraph: WordParagraphBlock) => {
    let blockType = 'unStyled';
    switch (wordParagraph.type) {
        case 'LaTex':
            blockType = 'LaTex';
            break;
        case 'Table':
            blockType = 'Table';
            break;
        case 'text':
            blockType = wordParagraph.paragraphStyle;
            break;
        default:
            break;
    }
    return blockType;
}

const convertWordParagraphToContentBlock = (wordParagraph: WordParagraphBlock) => {
    try {
        const {
            blockId = '',
            text,
            inlineStyleRanges
        } = wordParagraph;
        return {
            key: blockId,
            text,
            type: adaptWordParagraphTypeToBlockType(wordParagraph),
            inlineStyleRanges: inlineStyleRanges,
            entityRanges: [],
            data: {
                wordParagraph: deepCopy(wordParagraph)
            },
        }
    } catch (e) {
    }
}

const getTopicTitleParagraphStyle = (topic: TopicType): WordParagraphStyle => {
    if (topic.topicType == 'text' && topic.topicLevel) {
        if (
            isEmpty(topic.topicLevel) ||
            topic.topicLevel == undefined ||
            //@ts-ignore
            topic.topicLevel == 'undefined'
        ) {
            //TODO 如果是空的，暂时默认设置为二级标题吧 
            return `title_paragraph_${2}`;
        }
        //@ts-ignore
        return `title_paragraph_${Number(topic.topicLevel)}`;
        // return `title_paragraph_${Number(topic.topicLevel) + 1}`;
    }
    return 'normal_paragraph'
}

const getWordParagraphTitle = (topic: TopicType, wordParagraphList: WordParagraphBlock[]): WordParagraphBlock => {
    const serialNumber = topic.serialNumber;
    let topicWordParagraph: WordParagraphBlock = null;
    let titleBlockId = generateBlockId();
    if (wordParagraphList.length) {
        titleBlockId = wordParagraphList[0].blockId;
    }
    if (
        isEmpty(topic.topicLevel) ||
        topic.topicLevel == undefined ||
        //@ts-ignore
        topic.topicLevel == "undefined"
    ) {
        topic.topicLevel = '3'
    } else {
        if (Number(topic.topicLevel) > 6) {
            topic.topicLevel = '6';
        }
    }
    if (topic.topicLevel) {
        switch (topic.topicLevel) {
            case '1':
                const titleParagraph1Text = `第 ${serialNumber} 章  ${topic.topicName}`;
                topicWordParagraph = {
                    textTopicId: topic.id,
                    blockId: titleBlockId,
                    type: 'text',
                    text: titleParagraph1Text,
                    paragraphType: 'topic_title',
                    paragraphStyle: 'title_paragraph_1',
                    inlineStyleRanges: [
                        { length: titleParagraph1Text.length, offset: 0, style: 'BOLD' },
                        //@ts-ignore
                        { length: titleParagraph1Text.length, offset: 0, style: 'HeiTi' },
                    ],
                };
                break;
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
                const titleParagraphText = `${serialNumber} ${topic.topicName}`;
                let subTitleInlineStyleRanges: RawDraftInlineStyleRange[] = [];
                if (['2', '3'].includes(topic.topicLevel)) {
                    subTitleInlineStyleRanges = [
                        { length: titleParagraphText.length, offset: 0, style: 'BOLD' },
                        //@ts-ignore
                        { length: titleParagraphText.length, offset: 0, style: 'HeiTi' },
                    ]
                } else {
                    subTitleInlineStyleRanges = [
                        { length: titleParagraphText.length, offset: 0, style: 'BOLD' },
                        //@ts-ignore
                        { length: titleParagraphText.length, offset: 0, style: 'SongTi' },
                    ]
                }
                topicWordParagraph = {
                    textTopicId: topic.id,
                    blockId: titleBlockId,
                    type: 'text',
                    text: titleParagraphText,
                    paragraphType: 'topic_title',
                    paragraphStyle: `title_paragraph_${topic.topicLevel}`,
                    inlineStyleRanges: subTitleInlineStyleRanges
                };
                break;
            default:
                break;
        }
    }
    return topicWordParagraph;
}

const getDeviceParagraphBlockList = (
    textTopic: TopicType,
    childrenDeviceTopicList: TopicType[],
    nextEntityKey: number,
    newComDocInstance: DocInstance,
    tag: string
) => {
    try {
        if (textTopic.topicName == '草原植被恢复') {
        }
        //如果这个文本节点下有设施设备，就立即开始生成
        let deviceParagraphBlockList: WordParagraphBlock[] = [];
        if (childrenDeviceTopicList.length) {
            const topicDeviceParagraphListGroup = getDeviceParagraphListGroup(childrenDeviceTopicList);
            //这是整个段落的
            let allDeviceInlineContentSliceList: InlineContentSlice[] = [];
            let allDeviceBlockPlainText: string = ''; //预置拆分设施段落的文本
            let allDeviceBlockEntityRanges: DeviceEntityRange[] = []; //预置拆分设施段落的entityRanges
            topicDeviceParagraphListGroup.forEach((deviceParagraphGroup, deviceParagraphIndex) => {
                let tempDeviceInlineContentSliceList: InlineContentSlice[] = [];
                const currentTopic = deviceParagraphGroup.deviceTopicList[0];
                let needHighLight = false;
                if (currentTopic.isCustom) {
                    needHighLight = true;
                }
                //如果是设施节点
                if (deviceParagraphGroup.deviceGroupType == 'S') {
                    //每个设施分段中，暂时只处理包含一个设施节点的情况，如果超出，则需要抛出错误提示
                    //后续兼容或者在生成getDeviceParagraphListGroup过程中，把设施处理代码改成不要合并的方式
                    if (deviceParagraphGroup.deviceTopicList.length > 1) {
                        // toastShort('error', '设施节点处理异常，错误代码：' + deviceParagraphGroup.deviceTopicList[0].id)
                    }
                    const facilitiesBackgroundParagraphSliceList = deviceParagraphGroup.currentFacilitiesBackgroundParagraph.split(/[(\r\n)\r\n]+/);
                    if (facilitiesBackgroundParagraphSliceList.length > 1) {
                        //根据空格拆分预置段落
                        facilitiesBackgroundParagraphSliceList.forEach(facilitiesBackgroundParagraphSlice => {
                            let subDeviceInlineContentSliceList: InlineContentSlice[] = [];
                            let currentDeviceBlockPlainText: string = ''; //预置拆分设施段落的文本
                            let currentDeviceBlockEntityRanges: DeviceEntityRange[] = []; //预置拆分设施段落的entityRanges
                            //生成设备文本的切片
                            const _currentFacilitiesBackgroundParagraphSlice = generateDeviceParagraphSlice(facilitiesBackgroundParagraphSlice);
                            _currentFacilitiesBackgroundParagraphSlice.forEach((slice, sliceIndex) => {
                                switch (slice) {
                                    case '[*]':
                                    case '$[*]':
                                    case '$[*]':
                                    case '[NAME]':
                                    case '$[NAME]':
                                        const replacedText = getEntityText(slice, newComDocInstance, currentTopic);
                                        currentDeviceBlockPlainText = currentDeviceBlockPlainText + replacedText;
                                        if (needHighLight) {
                                            subDeviceInlineContentSliceList.push({
                                                content: replacedText,
                                                inlineStyleList: ['normal_inline_style', 'inline_background_color-#ffff00']
                                            })
                                        } else {
                                            subDeviceInlineContentSliceList.push({
                                                content: replacedText,
                                                inlineStyleList: ['normal_inline_style']
                                            })
                                        }
                                        break;
                                    case '$[S]':
                                    case '$[X]':
                                    case '$[N]':
                                    case '$[U]':
                                        const entityText = getEntityText(slice, newComDocInstance, currentTopic);
                                        if (!isEmpty(entityText)) {
                                            if (needHighLight) {
                                                subDeviceInlineContentSliceList.push({
                                                    content: entityText,
                                                    inlineStyleList: ['normal_inline_style', 'inline_background_color-#ffff00']
                                                })
                                            } else {
                                                subDeviceInlineContentSliceList.push({
                                                    content: entityText,
                                                    inlineStyleList: ['normal_inline_style']
                                                })
                                            }
                                            let tempEntityRange: DeviceEntityRange = {
                                                key: nextEntityKey,
                                                deviceAttributeType: slice,
                                                textTopicId: textTopic.id,
                                                deviceTopicId: currentTopic.id,
                                                text: entityText,
                                                textOffset: currentDeviceBlockPlainText.length,
                                                textLength: entityText.toString().length
                                            }
                                            currentDeviceBlockPlainText = currentDeviceBlockPlainText + entityText;
                                            currentDeviceBlockEntityRanges.push(tempEntityRange);
                                            nextEntityKey++;
                                        }
                                        break;
                                    default:
                                        const facilitiesBackgroundParagraphHighLightSliceList = maptchSplitHighLightTextSlice(slice);
                                        if (facilitiesBackgroundParagraphHighLightSliceList.length > 1) {
                                        }
                                        facilitiesBackgroundParagraphHighLightSliceList.forEach(facilitiesBackgroundParagraphHighLightSlice => {
                                            currentDeviceBlockPlainText = currentDeviceBlockPlainText + facilitiesBackgroundParagraphHighLightSlice.content;
                                            subDeviceInlineContentSliceList.push({
                                                content: facilitiesBackgroundParagraphHighLightSlice.content,
                                                inlineStyleList: facilitiesBackgroundParagraphHighLightSlice.inlineStyleList
                                            })
                                        })
                                        break;
                                }
                                // tempDeviceInlineContentSliceList
                            })
                            const deviceContentBlock = createContentBlockByInlineRanges(
                                subDeviceInlineContentSliceList,
                                'normal_paragraph',
                                textTopic.id + '_device_paragraph'
                            )
                            let tempDeviceParagraphBlock: WordParagraphBlock = {
                                textTopicId: textTopic.id,
                                blockId: generateBlockId(),
                                type: 'text',
                                text: deviceContentBlock.text,
                                inlineStyleRanges: deviceContentBlock.inlineStyleRanges,
                                entityRanges: currentDeviceBlockEntityRanges,
                                paragraphStyle: 'normal_paragraph',
                                paragraphType: 'device_background_paragraph',
                            }
                            deviceParagraphBlockList.push(tempDeviceParagraphBlock)
                        })
                    } else {
                        const _currentFacilitiesBackgroundParagraphSlice = generateDeviceParagraphSlice(deviceParagraphGroup.currentFacilitiesBackgroundParagraph);
                        // const currentTopic = deviceParagraphGroup.deviceTopicList[0];
                        _currentFacilitiesBackgroundParagraphSlice.forEach((slice, sliceIndex) => {
                            switch (slice) {
                                case '[*]':
                                case '$[*]':
                                case '$[*]':
                                case '[NAME]':
                                case '$[NAME]':
                                    const replacedText = getEntityText(slice, newComDocInstance, currentTopic);
                                    allDeviceBlockPlainText = allDeviceBlockPlainText + replacedText;
                                    allDeviceInlineContentSliceList.push({
                                        content: replacedText,
                                        inlineStyleList: ['normal_inline_style']
                                    })
                                    break;
                                case '$[S]':
                                case '$[X]':
                                case '$[N]':
                                case '$[U]':
                                    const entityText = getEntityText(slice, newComDocInstance, currentTopic);
                                    if (!isEmpty(entityText)) {
                                        allDeviceInlineContentSliceList.push({
                                            content: entityText,
                                            inlineStyleList: ['normal_inline_style']
                                        })
                                        let tempEntityRange: DeviceEntityRange = {
                                            key: nextEntityKey,
                                            deviceAttributeType: slice,
                                            textTopicId: textTopic.id,
                                            deviceTopicId: currentTopic.id,
                                            text: entityText,
                                            textOffset: allDeviceBlockPlainText.length,
                                            textLength: entityText.toString().length
                                        }
                                        allDeviceBlockPlainText = allDeviceBlockPlainText + entityText;
                                        allDeviceBlockEntityRanges.push(tempEntityRange);
                                        nextEntityKey++;
                                    }
                                    break;
                                default:
                                    const deviceBackgroundParagraphHighLightSliceList = maptchSplitHighLightTextSlice(slice);
                                    if (deviceBackgroundParagraphHighLightSliceList.length > 1) {
                                    }
                                    deviceBackgroundParagraphHighLightSliceList.forEach(deviceBackgroundParagraphHighLightSlice => {
                                        allDeviceBlockPlainText = allDeviceBlockPlainText + deviceBackgroundParagraphHighLightSlice.content;
                                        allDeviceInlineContentSliceList.push({
                                            content: deviceBackgroundParagraphHighLightSlice.content,
                                            inlineStyleList: deviceBackgroundParagraphHighLightSlice.inlineStyleList
                                        })
                                    })
                                    //旧版未处理高亮
                                    // allDeviceBlockPlainText = allDeviceBlockPlainText + slice;
                                    // allDeviceInlineContentSliceList.push({
                                    //     content: slice,
                                    //     inlineStyleList: ['normal_inline_style']
                                    // })
                                    break;
                            }
                        })
                    }
                } else {
                    //如果是设备节点
                    const _deviceBackgroundParagraphReplacedText = replaceDocInfo(deviceParagraphGroup.currentDeviceBackgroundParagraph, newComDocInstance);
                    allDeviceBlockPlainText = allDeviceBlockPlainText + _deviceBackgroundParagraphReplacedText;
                    allDeviceInlineContentSliceList.push({
                        content: _deviceBackgroundParagraphReplacedText,
                        inlineStyleList: ['normal_inline_style']
                    })
                    deviceParagraphGroup.deviceTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                        const currentTopic = deviceTopic;
                        const _currentDeviceConstituteParagraphSlice = generateDeviceParagraphSlice(deviceTopic.deviceBackgroundParagraph3);
                        const isLastConstituteParagraphSliceInfo: boolean = deviceTopicIndex === deviceParagraphGroup.deviceTopicList.length - 1;
                        _currentDeviceConstituteParagraphSlice.forEach((slice, sliceIndex) => {
                            switch (slice) {
                                case '[*]':
                                case '$[*]':
                                case '$[*]':
                                case '[NAME]':
                                case '$[NAME]':
                                    const replacedText = getEntityText(slice, newComDocInstance, currentTopic);
                                    allDeviceBlockPlainText = allDeviceBlockPlainText + replacedText;
                                    // allDeviceInlineContentSliceList.push({
                                    //     content: replacedText,
                                    //     inlineStyleList: ['normal_inline_style']
                                    // })
                                    if (needHighLight) {
                                        allDeviceInlineContentSliceList.push({
                                            content: replacedText,
                                            inlineStyleList: ['normal_inline_style', 'inline_background_color-#ffff00']
                                        })
                                    } else {
                                        allDeviceInlineContentSliceList.push({
                                            content: replacedText,
                                            inlineStyleList: ['normal_inline_style']
                                        })
                                    }
                                    break;
                                case '$[S]':
                                case '$[X]':
                                case '$[N]':
                                case '$[U]':
                                    const entityText = getEntityText(slice, newComDocInstance, currentTopic);
                                    if (!isEmpty(entityText)) {
                                        // allDeviceInlineContentSliceList.push({
                                        //     content: entityText,
                                        //     inlineStyleList: ['normal_inline_style']
                                        // })
                                        if (needHighLight) {
                                            allDeviceInlineContentSliceList.push({
                                                content: entityText,
                                                inlineStyleList: ['normal_inline_style', 'inline_background_color-#ffff00']
                                            })
                                        } else {
                                            allDeviceInlineContentSliceList.push({
                                                content: entityText,
                                                inlineStyleList: ['normal_inline_style']
                                            })
                                        }
                                        let tempEntityRange: DeviceEntityRange = {
                                            key: nextEntityKey,
                                            deviceAttributeType: slice,
                                            textTopicId: textTopic.id,
                                            deviceTopicId: currentTopic.id,
                                            text: entityText,
                                            textOffset: allDeviceBlockPlainText.length,
                                            textLength: entityText.toString().length
                                        }
                                        allDeviceBlockPlainText = allDeviceBlockPlainText + entityText;
                                        allDeviceBlockEntityRanges.push(tempEntityRange);
                                        nextEntityKey++;
                                    }
                                    if (slice === '$[U]') {
                                        if (isLastConstituteParagraphSliceInfo) {
                                            allDeviceBlockPlainText = allDeviceBlockPlainText + '。';
                                            allDeviceInlineContentSliceList.push({
                                                content: '。',
                                                inlineStyleList: ['normal_inline_style']
                                            })
                                        } else {
                                            allDeviceBlockPlainText = allDeviceBlockPlainText + '、';
                                            allDeviceInlineContentSliceList.push({
                                                content: '、',
                                                inlineStyleList: ['normal_inline_style']
                                            })
                                        }
                                    }
                                    break;
                                default:
                                    // const deviceBackgroundParagraphHighLightSliceList2 = maptchSplitHighLightTextSlice(slice);
                                    // if (deviceBackgroundParagraphHighLightSliceList2.length > 1) {
                                    // }
                                    // deviceBackgroundParagraphHighLightSliceList2.forEach(deviceBackgroundParagraphHighLightSlice2 => {
                                    //     allDeviceBlockPlainText = allDeviceBlockPlainText + deviceBackgroundParagraphHighLightSlice2.content;
                                    //     allDeviceInlineContentSliceList.push({
                                    //         content: slice,
                                    //         inlineStyleList: deviceBackgroundParagraphHighLightSlice2.inlineStyleList
                                    //     })
                                    // })
                                    //旧版本
                                    allDeviceBlockPlainText = allDeviceBlockPlainText + slice;
                                    allDeviceInlineContentSliceList.push({
                                        content: slice,
                                        inlineStyleList: ['normal_inline_style']
                                    })
                                    break;
                            }
                        })
                    })

                }
            })
            if (allDeviceInlineContentSliceList.length) {
                const allDeviceContentBlock = createContentBlockByInlineRanges(
                    allDeviceInlineContentSliceList,
                    'normal_paragraph',
                    textTopic.id + '_device_paragraph'
                )
                let allDeviceParagraphBlock: WordParagraphBlock = {
                    textTopicId: textTopic.id,
                    blockId: generateBlockId(),
                    type: 'text',
                    text: allDeviceContentBlock.text,
                    inlineStyleRanges: allDeviceContentBlock.inlineStyleRanges,
                    entityRanges: allDeviceBlockEntityRanges,
                    paragraphStyle: 'normal_paragraph',
                    paragraphType: 'device_background_paragraph',
                }
                deviceParagraphBlockList.push(allDeviceParagraphBlock)
            }
        }
        const deviceParagraphBlockListResult = {
            deviceParagraphBlockList,
            newNextEntityKey: nextEntityKey,
        }
        return deviceParagraphBlockListResult;
    } catch (e) {
    }
}

/**
 * 深度遍历指定树节点下级路径
 * @param topicTreeData 
 * @param childeDeviceType 
 * @returns 
 */
const findCheckedChildTopicList = (topicTreeData: TopicType[], childeDeviceType?: 'all' | 'S' | 'X'): TopicType[] => {
    let childTopicList: TopicType[] = [];
    topicTreeData.forEach(topic => {
        if (topic.topicType == 'text' && topic.children) {
            childTopicList = childTopicList.concat(findCheckedChildTopicList(topic.children, childeDeviceType))
        } else if (topic.topicType == 'device' && topic.checked) {
            if (
                childeDeviceType == 'all' || topic.deviceType == childeDeviceType
            ) {
                childTopicList.push(topic)
            }
        }
    })
    return childTopicList;
}

const findTargetTextTopicChildDeviceList = (
    topciTreeData: TopicType[],
    targetTextTopicName: string,
    childeDeviceType?: 'all' | 'S' | 'X'
): TopicType[] => {
    if (isEmpty(childeDeviceType)) {
        childeDeviceType = 'all'
    }
    let childDeviceList: TopicType[] = [];
    let hasFindTargetTopic = false;

    dfsRecursive(topciTreeData, (topic: TopicType, level: number) => {
        if (topic.topicType == 'text' && !hasFindTargetTopic) {
            if (topic.topicName === targetTextTopicName) {
                childDeviceList = findCheckedChildTopicList(topic.children, childeDeviceType);
                hasFindTargetTopic = true;
            }
        }
    })
    return childDeviceList;
};

const generateWordParagraphTitleByPlainText = (textTopic: TopicType, plainText: string): WordParagraphBlock => {
    let wordParagraphBlock: WordParagraphBlock = {
        textTopicId: textTopic.id,
        blockId: generateBlockId(),
        type: 'text',
        paragraphType: "custom_background_paragraph",
        text: plainText,
        //@ts-ignore
        paragraphStyle: `title_paragraph_${Number(textTopic.topicLevel) + 1}`,
        inlineStyleRanges: [
            {
                //@ts-ignore
                style: 'HeiTi',
                offset: 0,
                length: plainText.length,
            },
            {
                style: 'BOLD',
                offset: 0,
                length: plainText.length,
            },
            {
                //@ts-ignore
                style: 'normal_inline_style',
                offset: 0,
                length: plainText.length,
            }
        ]
    }
    return wordParagraphBlock;
}

const generateWordParagraphByPlainText = (textTopic: TopicType, plainText: string): WordParagraphBlock => {
    let wordParagraphBlock: WordParagraphBlock = {
        textTopicId: textTopic.id,
        blockId: generateBlockId(),
        type: 'text',
        paragraphType: "custom_background_paragraph",
        text: plainText,
        paragraphStyle: "normal_paragraph",
        inlineStyleRanges: [
            {
                //@ts-ignore
                style: 'wavy_inline_style',
                offset: 0,
                length: plainText.length,
            }
        ]
    }
    return wordParagraphBlock;
}

const getRandomThree = <T>(originList: T[]): T[] => {
    if (originList.length <= 3) {
        return originList;
    }
    let copyArr = [...originList];
    let result: T[] = [];
    for (let i = 0; i < 3; i++) {
        let randomIndex = Math.floor(Math.random() * copyArr.length);
        result.push(copyArr[randomIndex]);
        copyArr.splice(randomIndex, 1);
    }
    return result;
}

/**
 * 生成规划主要建设内容章节(2023-07-17修改为自动化采集一级节点)
 * @param topic 
 * @param _tempTopicTreeData 
 * @param topicTitleTagStatusConfig 
 * @returns 
 */
const generateMainContentsOfThePlanningChapter = (
    topic: TopicType,
    _tempTopicTreeData: TopicType[],
    topicTitleTagStatusConfig: TopicTitleTagStatusConfig,
    newComDocInstance: DocInstance,
    newComDocConfig: DocConfig
): WordParagraphBlock[] => {
    let topicWordParagraphList: WordParagraphBlock[] = [];
    const {
        newTableData,
    } = initExcelBuninessContentForWorker(
        newComDocInstance,
        newComDocConfig,
        [...initMergeCellBoundGroup],
        [...initTableHeader]
    );
    const newGridTableData: TableDataCell[][] = convertNewTableDataToGridTableData(newTableData);
    let newGridTableDataContent = [...newGridTableData].splice(5, newGridTableData.length - 11);
    newGridTableDataContent = newGridTableDataContent.filter(cellRowList => {
        return cellRowList[0].serialNumber && cellRowList[0].serialNumber.split('.').length == 1
    })
    newGridTableDataContent.forEach((tableCellRowGroup, tableCellRowGroupIndex) => {
        const tempSubTitleSerialNumber = topic.serialNumber + '.' + (tableCellRowGroupIndex + 1);
        const topLevelTopicName = tableCellRowGroup[1].text;
        if (['保护管理工程', '保护管理规划'].includes(topLevelTopicName)) {
            topicWordParagraphList.push(generateWordParagraphTitleByPlainText(topic, `${tempSubTitleSerialNumber} ${topLevelTopicName}`))
            let descriptionParagraphText = '严格执行《自然保护区管理条例》；加强保护管理，在保护区边界、功能区界、周边社区人为活动较为频繁的交通道口、重点保护的野生动植物分布地段以及生态旅游区，设立标识系统。';
            //开始生成确标定界章节切片
            const exactDemarcationDeviceTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "确标定界", 'S');
            if (exactDemarcationDeviceTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '开展确标定界，包括新建';
                exactDemarcationDeviceTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < exactDemarcationDeviceTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //开始生成保护管理体系章节切片
            const protectionAndManagementSystemTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "保护管理体系", 'S');
            if (protectionAndManagementSystemTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '完善保护管理体系，包括新建';
                protectionAndManagementSystemTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < protectionAndManagementSystemTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //开始生成野生植物保护规划章节切片
            const wildPlantConservationPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "野生植物保护规划", 'S');
            if (wildPlantConservationPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '加强国家重点保护动植物保护，进行植被恢复与栖息地恢复，开展';
                wildPlantConservationPlanningTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < wildPlantConservationPlanningTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //开始生成野生动物保护规划章节切片
            const wildPlantConservationAnimalTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "野生动物保护规划", 'S');
            if (wildPlantConservationAnimalTopicList.length) {
                if (wildPlantConservationPlanningTopicList.length === 0) {
                    descriptionParagraphText = descriptionParagraphText + '加强国家重点保护动植物保护，进行植被恢复与栖息地恢复，开展';
                }
                wildPlantConservationAnimalTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < wildPlantConservationAnimalTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //生态系统保护与修复规划
            const ecosystemProtectionAndRestorationPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "生态系统保护与修复规划", 'S');
            if (ecosystemProtectionAndRestorationPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '开展生态系统保护与修复，包括进行';
                ecosystemProtectionAndRestorationPlanningTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < ecosystemProtectionAndRestorationPlanningTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //防火规划-设施
            const firePreventionPlanningTopicListS = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "防火规划", 'S');
            if (firePreventionPlanningTopicListS.length) {
                descriptionParagraphText = descriptionParagraphText + '提升保护区防火能力建设，新建';
                firePreventionPlanningTopicListS.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < firePreventionPlanningTopicListS.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //防火规划-设备
            const firePreventionPlanningTopicListX = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "防火规划", 'X');
            if (firePreventionPlanningTopicListX.length) {
                descriptionParagraphText = descriptionParagraphText + '购置';
                const tempRandomList = getRandomThree(firePreventionPlanningTopicListX);
                tempRandomList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < tempRandomList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //有害生物防治-设施
            const pestControlTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "有害生物防治", 'S');
            if (pestControlTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '开展有害生物防治，包括新建';
                pestControlTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < pestControlTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，';
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。';
                    }
                })
            }
            //环境保护规划
            const environmentalProtectionPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "有害生物防治", 'S');
            if (environmentalProtectionPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '提升保护区环境质量，开展';
                environmentalProtectionPlanningTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < environmentalProtectionPlanningTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，';
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。';
                    }
                })
            }
            topicWordParagraphList.push(generateWordParagraphByPlainText(topic, descriptionParagraphText))
        }
        else if (['科研监测工程', '科研监测规划'].includes(topLevelTopicName)) {
            topicWordParagraphList.push(generateWordParagraphTitleByPlainText(topic, `${tempSubTitleSerialNumber} ${topLevelTopicName}`))
            // 【开展<随机选择3个科研研究规划下的项目>等科学研究】；
            // 【开展<随机选择3个监测项目规划下的项目>等监测项目，包括动植物的种类、生境调查等】；
            // 【提升保护区科研监测能力，新建<逐一列举科研监测设施设备节点下的设施>】；
            // 【加强科研队伍建设，包括引进科研人才，加强科研培训和交流，制定激励措施，优化科研环境等】。
            let descriptionParagraphText = '';
            //科研研究规划
            const scientificResearchPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "科研研究规划", 'all');
            if (scientificResearchPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '开展';
                const tempRandomList = getRandomThree(scientificResearchPlanningTopicList);
                tempRandomList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < tempRandomList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '等科学研究；'
                    }
                })
            }
            //监测项目规划
            const monitoringProjectPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "监测项目规划", 'all');
            if (monitoringProjectPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '开展';
                const tempRandomList = getRandomThree(monitoringProjectPlanningTopicList);
                tempRandomList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < tempRandomList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '等监测项目，包括动植物的种类、生境调查等；'
                    }
                })
            }
            //监测项目规划
            const scientificResearchMonitoringFacilitiesAndEquipmentTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "监测项目规划", 'all');
            if (scientificResearchMonitoringFacilitiesAndEquipmentTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '提升保护区科研监测能力，新建';
                scientificResearchMonitoringFacilitiesAndEquipmentTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < scientificResearchMonitoringFacilitiesAndEquipmentTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '；'
                    }
                })
                descriptionParagraphText += '加强科研队伍建设，包括引进科研人才，加强科研培训和交流，制定激励措施，优化科研环境等。';
            }
            topicWordParagraphList.push(generateWordParagraphByPlainText(topic, descriptionParagraphText))
        }
        else if (['宣传教育工程', '宣传教育规划'].includes(topLevelTopicName)) {
            topicWordParagraphList.push(generateWordParagraphTitleByPlainText(topic, `${tempSubTitleSerialNumber} ${topLevelTopicName}`))
            let descriptionParagraphText = '';
            const missionaryFacilitiesAndEquipmentTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "宣教设施设备", 'S');
            if (missionaryFacilitiesAndEquipmentTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '提供保护区宣传教育能力，';
                missionaryFacilitiesAndEquipmentTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < missionaryFacilitiesAndEquipmentTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '；'
                    }
                })
                descriptionParagraphText += '建立一批野外宣教点，健全教学和科研实践基地；制作专题宣传材料；开展社区居民的自然环境保护教育活动；加强职业培训教育等。';
            }
            topicWordParagraphList.push(generateWordParagraphByPlainText(topic, descriptionParagraphText))
        }
        else if (['可持续发展工程', '可持续发展规划'].includes(topLevelTopicName)) {
            topicWordParagraphList.push(generateWordParagraphTitleByPlainText(topic, `${tempSubTitleSerialNumber} ${topLevelTopicName}`))
            let descriptionParagraphText = '';
            const ecoTourismPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "生态旅游规划", 'S');
            if (ecoTourismPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '完善社区共管机制，制定社区经济发展项目扶持计划，推动保护区原住居民生产生活方式转型，引导社区健康、稳定发展。引导保护区周边群众兴办生态旅游配套设施，发展生态旅游，规划建设';
                ecoTourismPlanningTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < ecoTourismPlanningTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
                descriptionParagraphText += '开展资源合理利用，优化社区产业结构模式。';
            }
            topicWordParagraphList.push(generateWordParagraphByPlainText(topic, descriptionParagraphText))
        }
        else if (['基础设施工程', '基础设施规划'].includes(topLevelTopicName)) {
            topicWordParagraphList.push(generateWordParagraphTitleByPlainText(topic, `${tempSubTitleSerialNumber} ${topLevelTopicName}`))
            let descriptionParagraphText = '';
            //局站址建设规划
            const constructionPlanningOfBureauStationSiteTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "局站址建设规划", 'S');
            if (constructionPlanningOfBureauStationSiteTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '保护区的基础设施工程主要包括';
                constructionPlanningOfBureauStationSiteTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < constructionPlanningOfBureauStationSiteTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //绿化美化规划
            const greeningAndBeautificationPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "绿化美化规划", 'S');
            if (greeningAndBeautificationPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '进行绿化美化，开展';
                greeningAndBeautificationPlanningTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < greeningAndBeautificationPlanningTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //局站址建设规划-设备
            const constructionPlanningOfBureauStationSiteTopicListX = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "局站址建设规划", 'X');
            if (constructionPlanningOfBureauStationSiteTopicListX.length) {
                descriptionParagraphText = descriptionParagraphText + '购置基础办公设备、生活设备，包括';
                const tempRandomList = getRandomThree(constructionPlanningOfBureauStationSiteTopicListX);
                tempRandomList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < tempRandomList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //医疗救护规划
            const disasterPreventionAndMitigationPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "防灾减灾规划", 'S');
            if (disasterPreventionAndMitigationPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '提升防灾减灾能力，建设';
                disasterPreventionAndMitigationPlanningTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < disasterPreventionAndMitigationPlanningTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //排水规划
            const drainagePlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "排水规划", 'S');
            if (drainagePlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '建立';
                const tempRandomList = getRandomThree(drainagePlanningTopicList);
                tempRandomList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < tempRandomList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //供电通讯规划
            const powerSupplyCommunicationPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "供电通讯规划", 'S');
            if (powerSupplyCommunicationPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '建立';
                const tempRandomList = getRandomThree(powerSupplyCommunicationPlanningTopicList);
                tempRandomList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < tempRandomList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //道路建设规划
            const roadConstructionPlanningTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "道路建设规划", 'S');
            if (roadConstructionPlanningTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '建立';
                const tempRandomList = getRandomThree(roadConstructionPlanningTopicList);
                tempRandomList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < tempRandomList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            //智慧保护区
            const wisdomReserveTopicList = findTargetTextTopicChildDeviceList(_tempTopicTreeData, "智慧保护区", 'S');
            if (wisdomReserveTopicList.length) {
                descriptionParagraphText = descriptionParagraphText + '提升保护区智慧化、数字化建设，建立';
                wisdomReserveTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    descriptionParagraphText = descriptionParagraphText + `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`
                    if (deviceTopicIndex < wisdomReserveTopicList.length - 1) {
                        descriptionParagraphText = descriptionParagraphText + '，'
                    } else {
                        descriptionParagraphText = descriptionParagraphText + '。'
                    }
                })
            }
            topicWordParagraphList.push(generateWordParagraphByPlainText(topic, descriptionParagraphText))
        }
    })
    return topicWordParagraphList;
    // if (topic.topicName == '保护管理工程') {

    // }
    // else if (topic.topicName == '科研监测工程') {

    // }
    // else if (topic.topicName == '宣传教育工程') {

    // }
    // else if (topic.topicName == '可持续发展工程') {

    // }
    // else if (topic.topicName == '基础设施工程') {

    // }
}

/**
 * 生成规划目标章节
 * @param topic 
 * @param _tempTopicTreeData 
 * @param topicTitleTagStatusConfig 
 * @param newComDocInstance 
 * @returns 
 */
const generatePlanningGoalChapter = (
    topic: TopicType,
    _tempTopicTreeData: TopicType[],
    topicTitleTagStatusConfig: TopicTitleTagStatusConfig,
    newComDocInstance: DocInstance
): WordParagraphBlock[] => {
    const {
        protectlandBaseInfo: {
            protectlandName
        }
    } = newComDocInstance;
    let topicWordParagraphList: WordParagraphBlock[] = [];
    if (topic.topicName == '总体目标') {
        let descriptionParagraphText = `以生态环境建设和可持续发展的国家基本战略为指导，遵循自然规律，以科技为支撑，以资金投入为保障，以保护管理、科研监测、宣传教育设施建设为重点，加强森林生态系统保护，保持区内自然生态系统和自然景观资源的完整性，维护生态环境系统平衡；妥善处理自然保护与当地社区经济建设、居民生产生活的关系，促进区域社会经济的繁荣与稳定，充分发挥保护区的多功能效益。把${protectlandName}逐步建设成为功能区划合理、基础设施完备、管理科学高效、科研监测先进、社区经济协调发展，并具中国特色和国际影响力的自然保护区。`;
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, descriptionParagraphText))
    } else if (topic.topicName === '近期目标') {
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `近期着重进行保护工程、科研监测工程以及基础设施工程，用较短时间建立其较为完备的自然保护体系，建成森林生态系统完整、生态环境稳定的自然保护区。具体要实现以下几点：`));
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `1)逐步开展植被恢复，提高水源涵养能力，扩大生物生存空间。`));
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `2)加强科研队伍建设，作好科研监测工作，为珍稀、濒危物种的保存和繁衍创造条件。`));
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `3)加快保护区机构建设和职工队伍建设步伐，尽快形成较为完善的保护管理体系。`));
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `4)搞好保护区基础设施建设，使保护工程系统畅通无阻顺利进展。`));
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `5)在保护的前提下，积极探索保护区自然资源合理利用的途径。`));
        let descriptionParagraphText = `近期开展的工程包括`;
        let topicList: TopicType[] = tree2List(_tempTopicTreeData);
        const nearFutureDeviceTopicList = topicList.filter(topic => {
            return (
                topic.topicType == 'device' &&
                topic.isMainProjectChcked &&
                // Number(topic.nearFutureMoneyRateOfValue) >= Number(topic.mediumAndLongTermMoneyRateOfValue)
                Number(topic.nearFutureMoneyRate) >= Number(topic.mediumAndLongTermMoneyRate)
            )
        })
        nearFutureDeviceTopicList.forEach((deviceTopic, deviceTopicIndex) => {
            if (deviceTopicIndex < 10) {
                descriptionParagraphText += `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`;
                if (deviceTopicIndex < 9) {
                    descriptionParagraphText += '，';
                } else {
                    descriptionParagraphText += '等。';
                }
            }
        })
        descriptionParagraphText = replaceLastCharWithPeriod(descriptionParagraphText);
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, descriptionParagraphText))
    } else if (topic.topicName === '远期目标' || topic.topicName === '中长期目标') {
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `远期深入开展科研、保护和宣教活动，进一步完善基础设施配套建设，通过不断加强与国际国内学术交流与技术合作，提高经营管理和科学研究水平，更好的保护自然保护区的生态环境、生物资源及其生态过程，实现自然生态系统良性循环。积极探索资源可持续发展的有效途径，合理地利用环境资源发展经济，最终实现区域资源、环境与社会经济的可持续发展。将保护区建设成为生态环境优美、资源保护完好、管理科学、效益显著、和谐发展的自然保护区。具体包括：`));
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `1)基础配套工程建设全部完成，道路改造升级全面完成，资源保护和管理系统达到先进水平。`));
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `2)科研设施设备达到先进水平，科研人员每年都进行国际交流，科研人员整体素质得到提高，科研能力迅速增强，科研项目和经费得到充分保证，规范科研信息和成果，建立科技成果数据库，完善科研监测体系。`));
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `3)宣传教育内容丰富多彩，形式多种多样，不断提高社区群众的保护意识，调动社区群众积极参与保护工作，使群众掌握了一定的自然保护和科学技术知识，使环保意识和法律观念深入人心。`));
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, `4)通过生态旅游基础设施的建设和多种经营项目的实施，提高保护区经济发展能力。`));
        let descriptionParagraphText = `中长期完成的工程包括`;
        let topicList: TopicType[] = tree2List(_tempTopicTreeData);
        const farFutureDeviceTopicList = topicList.filter(topic => {
            return (
                topic.topicType == 'device' &&
                topic.isMainProjectChcked &&
                // Number(topic.mediumAndLongTermMoneyRateOfValue) >= Number(topic.nearFutureMoneyRateOfValue)
                Number(topic.mediumAndLongTermMoneyRate) >= Number(topic.nearFutureMoneyRate)
            )
        })
        farFutureDeviceTopicList.forEach((deviceTopic, deviceTopicIndex) => {
            if (deviceTopicIndex < 10) {
                descriptionParagraphText += `${deviceTopic.topicName}${deviceTopic.count}${deviceTopic.unit}`;
                if (deviceTopicIndex < 9) {
                    descriptionParagraphText += '，';
                } else {
                    descriptionParagraphText += '等。';
                }
            }
        })
        descriptionParagraphText = replaceLastCharWithPeriod(descriptionParagraphText);
        topicWordParagraphList.push(generateWordParagraphByPlainText(topic, descriptionParagraphText))
    }
    return topicWordParagraphList;
}

function removeAndAdjustColumn(
    tabledata: any[][],
    colIndex: number,
    rowSpanList: RowSpanInfo[],
    colSpanList: ColSpanInfo[]
) {
    // 1. 删除指定列
    const adjustedData = tabledata.map(row => {
        const newRow = [...row];
        newRow.splice(colIndex, 1);
        return newRow;
    });

    // 2. 调整行和列合并
    rowSpanList.forEach(item => {
        if (item.colIndex === colIndex) {
            const index = rowSpanList.indexOf(item);
            rowSpanList.splice(index, 1);
        } else if (item.colIndex > colIndex) {
            item.colIndex--;
        }
    });

    colSpanList.forEach(item => {
        if (item.colIndex <= colIndex && colIndex < item.colIndex + item.colSpan) {
            //@ts-ignore
            item.deleteCount++;
            //@ts-ignore
            if (item.deleteCount === item.originColSpan) {
                const index = colSpanList.indexOf(item);
                colSpanList.splice(index, 1);
            } else {
                item.colSpan--;
            }
        } else if (item.colIndex > colIndex) {
            item.colIndex--;
        }
    });
    rowSpanList = adjustColIndexes(rowSpanList);
    return adjustedData;
}

function adjustColIndexes(data) {
    // 先对数组按 colIndex 排序
    data.sort((a, b) => a.colIndex - b.colIndex);

    // 遍历数组检查并调整重复的 colIndex
    for (let i = 0; i < data.length; i++) {
        // 检查当前元素与前一个元素是否有重复的 colIndex
        if (i > 0 && data[i].colIndex === data[i - 1].colIndex) {
            // 检查是否有空缺
            if (i === 1 || data[i].colIndex - data[i - 2].colIndex > 1) {
                // 将前一个 colIndex 减 1
                data[i - 1].colIndex--;
            }
        }

        // 检查当前元素与后一个元素是否有重复的 colIndex
        if (i < data.length - 1 && data[i].colIndex === data[i + 1].colIndex) {
            // 检查是否有空缺
            if (i === data.length - 2 || data[i + 2].colIndex - data[i].colIndex > 1) {
                // 将后一个 colIndex 加 1
                data[i + 1].colIndex++;
            }
        }
    }

    // 返回调整后的数据
    return data;
}

const findCellValuColIndex = (rowList: string[], cellValue: string): number => {
    let colIndex = -1;
    for (let i = 0; i < rowList.length; i++) {
        if (rowList[i] == cellValue) {
            colIndex = i;
            break;
        }
    }
    return colIndex;
}

/**
 * 根据制定规则删除表格列，以及自动调整修改后的单元格合并关系
 * @param tableData 
 * @param tableColSpanInfoList 
 * @param tableRowSpanInfoList 
 * @param checkColumnNeedDeleteFun 
 * @returns 
 */
const deleteTableDataEmptyColumn = (
    tableData: string[][],
    tableColSpanInfoList: ColSpanInfo[],
    tableRowSpanInfoList: RowSpanInfo[],
    startRowIndex: number,
    startColIndex: number,
    checkColumnNeedDeleteFun?: (tableData: string[][], colIndex: number, startRowIndex: number) => boolean
): {
    tableData: string[][],
    tableColSpanInfoList: ColSpanInfo[],
    tableRowSpanInfoList: RowSpanInfo[]
} => {
    if (isEmpty(startRowIndex)) {
        startRowIndex = 0;
    }
    const checkTableColumnIsAllEmpty = (tableData: string[][], colIndex: number, startRowIndex: number): boolean => {
        if(colIndex <  startColIndex){
            return false;
        }
        let tableColumnIsAllEmpty: boolean = true;
        tableData.forEach(rowList => {
            if (!isEmpty(rowList[colIndex]) && Number(rowList[colIndex]) > 0) {
                tableColumnIsAllEmpty = false;
            }
        })
        return tableColumnIsAllEmpty;
    }
    let handledTableData: string[][] = [...tableData];
    let handledTableColSpanInfoList: ColSpanInfo[] = [...tableColSpanInfoList];
    let handledTableRowSpanInfoList: RowSpanInfo[] = [...tableRowSpanInfoList];
    let columnIsEmptyOrNullIndexList: number[] = [];
    for (let i = 0; i < tableData[0].length; i++) {
        const tableColumnIsNeedToDelete = checkColumnNeedDeleteFun ? checkColumnNeedDeleteFun(tableData, i, startRowIndex) : checkTableColumnIsAllEmpty(tableData, i, startRowIndex);
        if (tableColumnIsNeedToDelete) {
            columnIsEmptyOrNullIndexList.push(i);
        }
    }
    columnIsEmptyOrNullIndexList.forEach((columnIndex, _index) => {
        handledTableData = removeAndAdjustColumn(handledTableData, columnIndex - _index, handledTableRowSpanInfoList, handledTableColSpanInfoList)
    })
    return {
        tableData: handledTableData,
        tableColSpanInfoList: handledTableColSpanInfoList,
        tableRowSpanInfoList: handledTableRowSpanInfoList
    }
}

/**
 * 
 * @param tempTopicTreeData 
 * @param newComDocInstance 
 * @param newComDocConfig 
 * @returns 
 */
const getInvestmentArrangementContent = (
    topic: TopicType,
    newComDocInstance: DocInstance,
    newComDocConfig: DocConfig,
    includeTableNameInfo: boolean
): {
    tableData: string[][],
    rowSpanInfoList: RowSpanInfo[],
    colSpanInfoList: ColSpanInfo[],
    tableName: string,
    paragraphTextList: string[]
} => {
    try {
        const paragraphTextList: string[] = [];
        const {
            newTableData,
            newMergeCellBoundGroud
        } = initExcelBuninessContentForWorker(
            deepCopy(newComDocInstance),
            newComDocConfig,
            [...initMergeCellBoundGroup],
            [...initTableHeader]
        );
        const investmentArrangementTable: string[][] = [
            ["序号", "建设项目", "合计", "占建设投资的比例", "分项投资估算", "", "", "分期投资估算", ""],
            ["", "", "", "", "建筑", "设备", "其它", "近期", "中长期"],
        ];
        const colSpanInfoList: ColSpanInfo[] = [
            {
                rowIndex: 0,
                colIndex: 4,
                colSpan: 3,
            },
            {
                rowIndex: 0,
                colIndex: 7,
                colSpan: 2,
            },
        ]
        const rowSpanInfoList: RowSpanInfo[] = [
            {
                rowIndex: 0,
                colIndex: 0,
                rowSpan: 2,
            },
            {
                rowIndex: 0,
                colIndex: 1,
                rowSpan: 2,
            },
            {
                rowIndex: 0,
                colIndex: 2,
                rowSpan: 2,
            },
            {
                rowIndex: 0,
                colIndex: 3,
                rowSpan: 2,
            }
        ]
        const newGridTableData: TableDataCell[][] = convertNewTableDataToGridTableData(newTableData);
        let newGridTableDataContent = [...newGridTableData].splice(5, newGridTableData.length - 11);
        newGridTableDataContent = newGridTableDataContent.filter(cellRowList => {
            return cellRowList[0].serialNumber && cellRowList[0].serialNumber.split('.').length == 1
        })
        if (newGridTableData.length >= 6) {
            const totalRowData = [];
            const totalCellRowData = newGridTableData[3];
            const constructionCostCellRowData = newGridTableData[4];
            totalRowData.push('');
            totalRowData.push('合计');
            totalRowData.push(totalCellRowData[5] ? totalCellRowData[5].text : '');
            totalRowData.push('100%');
            //
            totalRowData.push(totalCellRowData[6].text);
            totalRowData.push(totalCellRowData[7].text);
            totalRowData.push(totalCellRowData[8].text);
            //
            totalRowData.push(totalCellRowData[9].text);
            totalRowData.push(totalCellRowData[10].text);
            investmentArrangementTable.push(totalRowData);
            newGridTableDataContent.forEach(cellRowList => {
                const rowData = [];
                rowData.push(cellRowList[0].serialNumber);
                rowData.push(cellRowList[1].text);
                rowData.push(cellRowList[5].text);
                rowData.push(parsePrice(cellRowList[5].text / totalCellRowData[5].text) + '%');
                //
                rowData.push(cellRowList[6].text);
                rowData.push(cellRowList[7].text);
                rowData.push(cellRowList[8].text);
                //
                rowData.push(cellRowList[9].text);
                rowData.push(cellRowList[10].text);
                investmentArrangementTable.push(rowData)
            })
            const otherExpensesCellRowData = newGridTableData[newGridTableData.length - 6];
            const reserveFeeRowCellData = newGridTableData[newGridTableData.length - 1];
            const otherExpensesRowData = [];
            const reserveFeeRowData = [];
            otherExpensesRowData.push(otherExpensesCellRowData[0].text);
            otherExpensesRowData.push(otherExpensesCellRowData[1].text);
            otherExpensesRowData.push(otherExpensesCellRowData[5] ? otherExpensesCellRowData[5].text : '');
            otherExpensesRowData.push(parsePrice(otherExpensesCellRowData[5].text / totalCellRowData[5].text) + '%');
            //
            otherExpensesRowData.push(otherExpensesCellRowData[6].text);
            otherExpensesRowData.push(otherExpensesCellRowData[7].text);
            otherExpensesRowData.push(otherExpensesCellRowData[8].text);
            //
            otherExpensesRowData.push(otherExpensesCellRowData[9].text);
            otherExpensesRowData.push(otherExpensesCellRowData[10].text);
            investmentArrangementTable.push(otherExpensesRowData);
            //预备费
            reserveFeeRowData.push(reserveFeeRowCellData[0].text);
            reserveFeeRowData.push(reserveFeeRowCellData[1].text);
            reserveFeeRowData.push(reserveFeeRowCellData[5] ? reserveFeeRowCellData[5].text : '');
            reserveFeeRowData.push(parsePrice(reserveFeeRowCellData[5].text / totalCellRowData[5].text) + '%');
            //
            reserveFeeRowData.push(reserveFeeRowCellData[6].text);
            reserveFeeRowData.push(reserveFeeRowCellData[7].text);
            reserveFeeRowData.push(reserveFeeRowCellData[8].text);
            //
            reserveFeeRowData.push(reserveFeeRowCellData[9].text);
            reserveFeeRowData.push(reserveFeeRowCellData[10].text);
            investmentArrangementTable.push(reserveFeeRowData);
            const paragraphText1 = `经估算，项目建设投资额为${investmentArrangementTable[2][2]}万元，其中，工程建设费用${investmentArrangementTable[3][2]}万元，工程建设其他费用${investmentArrangementTable[investmentArrangementTable.length - 2][2]}万元，工程预备费${investmentArrangementTable[investmentArrangementTable.length - 1][2]}万元。`;
            paragraphTextList.push(paragraphText1);
            let paragraphText2 = '工程建设费用中，包括';
            newGridTableDataContent.forEach((rowDataList, rowIndex) => {
                const percent = parsePrice(rowDataList[5].text / constructionCostCellRowData[5].text) + '%';
                paragraphText2 += rowDataList[1].text + `${rowDataList[5].text}万元，占投资的${percent}`;
                if (rowIndex < newGridTableDataContent.length - 1) {
                    paragraphText2 += '；';
                } else {
                    paragraphText2 += '。'
                }
            })
            const constructionCostPrcent = parsePrice(totalCellRowData[6].text / totalCellRowData[5].text) + '%';
            const equipmentInstallationPercent = parsePrice(totalCellRowData[7].text / totalCellRowData[5].text) + '%';
            const otherExpensesPercent = parsePrice(otherExpensesCellRowData[5].text / totalCellRowData[5].text) + '%';
            const paragraphText3 = `按资金用途分，建筑费${totalCellRowData[6].text}万元，占投资的${constructionCostPrcent}；设备及安装费${totalCellRowData[7].text}万元，占投资的${equipmentInstallationPercent}；其它费用${otherExpensesCellRowData[5].text}万元，占投资的${otherExpensesPercent}。`;
            const constructionCostPercent1 = parsePrice(constructionCostCellRowData[9].text / constructionCostCellRowData[5].text) + '%';
            const constructionCostPercent2 = parsePrice(constructionCostCellRowData[10].text / constructionCostCellRowData[5].text) + '%';
            let paragraphText4 = `按建设期限分，近期投资${constructionCostCellRowData[9].text}万元，占投资的${constructionCostPercent1}；中长期投资${constructionCostCellRowData[10].text}万元，占投资的${constructionCostPercent2} 。`;
            if (includeTableNameInfo) {
                paragraphText4 += `具体情况见表${topic.serialNumber.split('.')[0]}-1。`;
            }
            paragraphTextList.push(paragraphText2);
            paragraphTextList.push(paragraphText3);
            paragraphTextList.push(paragraphText4);
        }
        const investmentArrangementTableName = topic.serialNumber.split('.')[0] + '-1 投资项目构成汇总表';
        return {
            tableData: investmentArrangementTable,
            rowSpanInfoList: rowSpanInfoList,
            colSpanInfoList: colSpanInfoList,
            tableName: investmentArrangementTableName,
            paragraphTextList: paragraphTextList
        }
    } catch (e) {
        console.error("生成投资计划表内容失败--->", e);
    }
}

/**
 * 生成投资计划安排章节
 * @param topic 
 * @param _tempTopicTreeData 
 * @param topicTitleTagStatusConfig 
 * @param newComDocInstance 
 * @param newComDocConfig 
 * @returns 
 */
const generateInvestmentArrangementChapter = (
    topic: TopicType,
    _tempTopicTreeData: TopicType[],
    topicTitleTagStatusConfig: TopicTitleTagStatusConfig,
    newComDocInstance: DocInstance,
    newComDocConfig: DocConfig
): WordParagraphBlock[] => {
    try {
        let wordParagraphList: WordParagraphBlock[] = [];
        const {
            tableData,
            rowSpanInfoList,
            colSpanInfoList,
            tableName,
            paragraphTextList
        } = getInvestmentArrangementContent(
            topic,
            newComDocInstance,
            newComDocConfig,
            true,
        )
        paragraphTextList.forEach((paragraphText, index) => {
            wordParagraphList.push(generateWordParagraphByPlainText(topic, paragraphText))
        })
        wordParagraphList.push({
            type: 'text',
            blockId: generateBlockId(),
            textTopicId: topic.id,
            text: tableName,
            //@ts-ignore
            inlineStyleRanges: [{ style: 'normal_inline_style', length: tableName.length, offset: 0 }],
            paragraphStyle: 'table_name_paragraph',
            paragraphType: 'custom_background_paragraph',
        })
        wordParagraphList.push({
            type: 'Table',
            blockId: generateBlockId(),
            textTopicId: topic.id,
            tableColSpanList: colSpanInfoList,
            tableRowSpanList: rowSpanInfoList,
            tableData: tableData,
            text: '表格',
            tableName: tableName,
            tableHeaderRowIndex: 1,
            //@ts-ignore
            inlineStyleRanges: [{ style: 'normal_inline_style', length: 2, offset: 0 }],
        })
        return wordParagraphList;
    } catch (e) {
        return []
    }
}

/**
 * 深度遍历指定树节点下级路径
 * @param topicTreeData 
 * @param childeDeviceType 
 * @returns 
 */
const findMainProjectCheckedChildTopicList = (topicTreeData: TopicType[]): TopicType[] => {
    let childTopicList: TopicType[] = [];
    topicTreeData.forEach(topic => {
        if (topic.topicType == 'text' && topic.children) {
            childTopicList = childTopicList.concat(findMainProjectCheckedChildTopicList(topic.children))
        } else if (topic.topicType == 'device' && topic.checked && topic.isMainProjectChcked) {
            if (
                topic.isMainProjectChcked
            ) {
                childTopicList.push(topic)
            }
        }
    })
    return childTopicList;
}

const findMainProjectCheckedDeviceTopicList = (
    topciTreeData: TopicType[],
    targetTextTopicName: string,
): TopicType[] => {
    let childDeviceList: TopicType[] = [];
    let hasFindTargetTopic = false;

    dfsRecursive(topciTreeData, (topic: TopicType, level: number) => {
        if (topic.topicType == 'text' && !hasFindTargetTopic) {
            if (topic.topicName === targetTextTopicName) {
                childDeviceList = findMainProjectCheckedChildTopicList(topic.children);
                hasFindTargetTopic = true;
            }
        }
    })
    return childDeviceList;
}

const findTextTopicChildTopicListOneLayer = (
    topciTreeData: TopicType[],
    targetTextTopicName: string,
) => {
    let childDeviceList: TopicType[] = [];
    let hasFindTargetTopic = false;

    dfsRecursive(topciTreeData, (topic: TopicType, level: number) => {
        if (topic.topicType == 'text' && !hasFindTargetTopic) {
            if (topic.topicName === targetTextTopicName) {
                childDeviceList = topic.children;
                hasFindTargetTopic = true;
            }
        }
    })
    return childDeviceList;
}

const spliceChildrenDeviceTopicList = (
    childrenDeviceTopicList: TopicType[]
): TopicType[][] => {
    let deviceTopicGroupList: TopicType[][] = [];
    childrenDeviceTopicList.forEach((deviceTopic, index) => {
        if (deviceTopicGroupList.length == 0) {
            deviceTopicGroupList.push([deviceTopic]);
        } else {
            const lastIndex = deviceTopicGroupList.length - 1;
            const lastSubIndex = deviceTopicGroupList[lastIndex].length - 1;
            if (deviceTopicGroupList[lastIndex].length >= 2) {
                if (deviceTopic.deviceType == 'X') {
                    deviceTopicGroupList[lastIndex].push(deviceTopic);
                } else {
                    deviceTopicGroupList.push([deviceTopic])
                }
            } else {
                deviceTopicGroupList[lastIndex].push(deviceTopic);
            }
        }
    })
    return deviceTopicGroupList
}

/**
 * 生成重点工程章节
 * @param topic 
 * @param _tempTopicTreeData 
 * @param topicTitleTagStatusConfig 
 * @param newComDocInstance 
 */
const generateonKeyProjectsChapter = (
    topic: TopicType,
    _tempTopicTreeData: TopicType[],
    topicTitleTagStatusConfig: TopicTitleTagStatusConfig,
    newComDocInstance: DocInstance,
    newComDocConfig: DocConfig
): WordParagraphBlock[] => {
    const tempTopicTreeData = [...deepCopy(_tempTopicTreeData)];
    let topicWordParagraphList: WordParagraphBlock[] = [];
    const {
        protectlandBaseInfo: {
            protectlandName
        }
    } = newComDocInstance;
    const {
        newTableData,
        newMergeCellBoundGroud
    } = initExcelBuninessContentForWorker(
        deepCopy(newComDocInstance),
        newComDocConfig,
        [...initMergeCellBoundGroup],
        [...initTableHeader]
    );
    const planningTopicCellList = newTableData.filter(tableCell => {
        return (
            tableCell.bound[1] >= 5 &&
            tableCell.bound[0] == 1 &&
            tableCell.serialNumber.split('.').length == 1 &&
            !tableCell.id.includes('-')
        )
    })
    let titleTopicList: TopicType[] = [];
    const _tempTopicList: TopicType[] = [...newComDocInstance.topicList];
    planningTopicCellList.forEach(tableCell => {
        const findTextTopic = _tempTopicList.find(item => {
            return item.id == tableCell.id;
        })
        if (findTextTopic) {
            const findTopicChildList = findTextTopicChildTopicListOneLayer(tempTopicTreeData, findTextTopic.topicName);
            findTopicChildList.forEach(subTextTopic => {
                const mainProjectCheckedChildTopicList = findMainProjectCheckedDeviceTopicList(tempTopicTreeData, subTextTopic.topicName);
                if (mainProjectCheckedChildTopicList.length) {
                    subTextTopic.subTopicList = mainProjectCheckedChildTopicList;
                } else {
                    subTextTopic.subTopicList = [];
                }
            })
            const hasMainProjectCheckedChildSubTopicList = findTopicChildList.filter(subTextTopic => {
                return subTextTopic.subTopicList.length;
            })
            if (hasMainProjectCheckedChildSubTopicList.length) {
                findTextTopic.subTopicList = hasMainProjectCheckedChildSubTopicList;
                titleTopicList.push(findTextTopic);
            }
        }
    })
    titleTopicList.forEach((textTopic, textTopicIndex) => {
        const textTopicTitlePlainText = `${topic.serialNumber}.${textTopicIndex + 1}   ${textTopic.topicName}`;
        const titleParagraph = generateWordParagraphByPlainText(topic, textTopicTitlePlainText);
        titleParagraph.paragraphStyle = 'title_paragraph_2';
        //@ts-ignore
        titleParagraph.inlineStyleRanges.push({ length: textTopicTitlePlainText.length, offset: 0, style: 'HeiTi' });
        titleParagraph.inlineStyleRanges.push({ length: textTopicTitlePlainText.length, offset: 0, style: 'BOLD' });
        topicWordParagraphList.push(titleParagraph)
        textTopic.subTopicList.forEach((subTextTopic, subTextTopicIndex) => {
            const subTextTopicTitlePlainText = `${topic.serialNumber}.${textTopicIndex + 1}.${subTextTopicIndex + 1}   ${subTextTopic.topicName}`;
            const subTitleParagraph = generateWordParagraphByPlainText(topic, subTextTopicTitlePlainText);
            subTitleParagraph.paragraphStyle = 'title_paragraph_3';
            //@ts-ignore
            subTitleParagraph.inlineStyleRanges.push({ length: subTextTopicTitlePlainText.length, offset: 0, style: 'HeiTi' })
            subTitleParagraph.inlineStyleRanges.push({ length: subTextTopicTitlePlainText.length, offset: 0, style: 'BOLD' })
            topicWordParagraphList.push(subTitleParagraph)
            const childrenDeviceTopicList = subTextTopic.subTopicList;
            const deviceTopicGroupList = spliceChildrenDeviceTopicList(subTextTopic.subTopicList);
            //设施文本分段生成，2个设施的文本生成一段，设备文本单独生成一段或者合并到设施文本中(采用并入的方式)
            deviceTopicGroupList.forEach(deviceTopicGroup => {
                const {
                    deviceParagraphBlockList,
                    newNextEntityKey
                } = getDeviceParagraphBlockList(topic, deviceTopicGroup, 1, newComDocInstance, 'generateonKeyProjectsChapter');
                let deviceParagraphPlainText = '';
                deviceParagraphBlockList.forEach(deviceParagraph => {
                    deviceParagraphPlainText += deviceParagraph.text;
                })
                const deviceNormalParagraph = generateWordParagraphByPlainText(topic, deviceParagraphPlainText);
                topicWordParagraphList.push(deviceNormalParagraph)
            })
        })
    })
    const topicSortNumber = topic.serialNumber.split('.')[0];
    // 表 [NAME]主要建设项目规划表
    const tableNameParagraph = generateWordParagraphByPlainText(topic, `表${topicSortNumber}-1 ${protectlandName}主要建设项目规划表`);
    tableNameParagraph.paragraphStyle = 'table_name_paragraph';
    topicWordParagraphList.push(tableNameParagraph);
    const tableOfKeyProjects = createTableOfKeyProjects(_tempTopicTreeData)
    tableOfKeyProjects.textTopicId = topic.id;
    tableOfKeyProjects.blockId = generateBlockId();
    tableOfKeyProjects.text = '表格'
    tableOfKeyProjects.entityRanges = [];
    topicWordParagraphList.push(tableOfKeyProjects);
    return topicWordParagraphList;
}



const generateProtectlandProblemChapter = (
    topic: TopicType,
    _tempTopicTreeData: TopicType[],
    topicTitleTagStatusConfig: TopicTitleTagStatusConfig,
    newComDocInstance: DocInstance
): WordParagraphBlock[] => {
    let topicWordParagraphList: WordParagraphBlock[] = [];
    const {
        protectlandBaseInfo: {
            protectlandName,
            protectlandProblemList
        }
    } = newComDocInstance;
    if (protectlandProblemList.length) {
        const protectlandProblemValueStr = protectlandProblemList[0];
        const protectlandProblemValueList = protectlandProblemValueStr.split(',');
        protectlandProblemValueList.forEach((value, index) => {
            const findProblem = protectlandProblemTableData.find(protectlandProblem => {
                return protectlandProblem.value == value;
            })
            if (findProblem) {
                const problemTitleParagragph: WordParagraphBlock = generateWordParagraphByPlainText(topic, `（${index + 1}） ${replaceDocInfo(findProblem.problemDetails, newComDocInstance)}`);
                problemTitleParagragph.paragraphStyle = 'title_paragraph_5';
                problemTitleParagragph.paragraphType = 'custom_background_paragraph';
                topicWordParagraphList.push(problemTitleParagragph);
                const problemBackgroundParagraphList: string[] = [];
                if (!isEmpty(findProblem.backgroundParagraph1)) {
                    problemBackgroundParagraphList.push(findProblem.backgroundParagraph1)
                }
                if (!isEmpty(findProblem.backgroundParagraph2)) {
                    problemBackgroundParagraphList.push(findProblem.backgroundParagraph2)
                }
                if (!isEmpty(findProblem.backgroundParagraph3)) {
                    problemBackgroundParagraphList.push(findProblem.backgroundParagraph3)
                }
                if (!isEmpty(findProblem.backgroundParagraph4)) {
                    problemBackgroundParagraphList.push(findProblem.backgroundParagraph4)
                }
                const problemCurrentBackgroundParagraph = lotteryStringList(problemBackgroundParagraphList);
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, replaceDocInfo(problemCurrentBackgroundParagraph, newComDocInstance)));
            }
        })
    }
    return topicWordParagraphList;
}


const extractLeafDeviceTopicList = (tree: TopicType[], targetId: string): TopicType[] => {
    let leafNodes = [];

    function isLeafNode(node: TopicType) {
        return !node.children || node.children.length === 0 && node.topicType == 'device';
    }

    function dfs(node: TopicType, target) {
        if (node.id === target) {
            // 如果找到了目标节点，就开始收集叶子节点
            collectLeafNodes(node);
        } else if (node.children) {
            for (let child of node.children) {
                dfs(child, target);
            }
        }
    }

    function collectLeafNodes(node) {
        if (isLeafNode(node)) {
            leafNodes.push(node);
        } else if (node.children) {
            for (let child of node.children) {
                collectLeafNodes(child);
            }
        }
    }

    for (let node of tree) {
        dfs(node, targetId);
    }

    return leafNodes;
}

const createTableOfKeyProjects = (
    tempTopicTreeData: TopicType[]
): WordParagraphBlock => {
    let wordParagraphBlockOfTable: WordParagraphBlock = {
        type: 'Table',
        tableName: '总体规划重点工程表',
        tableColSpanList: [
            {
                colIndex: 2,
                colSpan: 2,
                rowIndex: 0
            },
            {
                colIndex: 4,
                colSpan: 2,
                rowIndex: 0
            },
        ],
        tableRowSpanList: [
            {
                rowIndex: 0,
                colIndex: 0,
                rowSpan: 2,
            },
            {
                rowIndex: 0,
                colIndex: 1,
                rowSpan: 2,
            }
        ]
    };
    let tableData = [
        ['分类', '工程项目名称', '建设规模', '', '建设期限', ''],
        ['', '', '单位', '数量', '近期', '远期'],
    ]
    dfsRecursive(tempTopicTreeData, (topic: TopicType, level: number) => {
        if (level == 1) {
            let deviceTopicList = extractLeafDeviceTopicList(tempTopicTreeData, topic.id)
            deviceTopicList = deviceTopicList.filter(ele => {
                return ele.isMainProjectChcked && ele.checked;
            })
            if (deviceTopicList.length) {
                let tempRowSpanInfo: RowSpanInfo = {
                    rowIndex: tableData.length,
                    rowSpan: deviceTopicList.length,
                    colIndex: 0
                }
                wordParagraphBlockOfTable.tableRowSpanList.push(tempRowSpanInfo);
                deviceTopicList.forEach((deviceTopic, deviceTopicIndex) => {
                    tableData.push([
                        deviceTopicIndex == 0 ? topic.topicName : '',
                        deviceTopic.topicName,
                        deviceTopic.unit,
                        deviceTopic.unitPrice,
                        deviceTopic.nearFutureMoneyRate && Number(deviceTopic.nearFutureMoneyRate) > 0 ? '√' : '',
                        deviceTopic.mediumAndLongTermMoneyRate && Number(deviceTopic.mediumAndLongTermMoneyRate) > 0 ? '√' : '',
                        // deviceTopic.nearFutureMoneyRate && Number(deviceTopic.nearFutureMoneyRate) > 0 ? '-' : '',
                        // deviceTopic.mediumAndLongTermMoneyRate && Number(deviceTopic.mediumAndLongTermMoneyRate) > 0 ? '-' : '',
                    ])
                })
            }
        }
    })
    wordParagraphBlockOfTable.tableData = tableData;
    return wordParagraphBlockOfTable;
}

/**
 * 检查是否是指定父节点下的最后一个节点
 * @param topic 
 * @param tempTopicTreeData 
 */
const checkTopicIsLastNodeOfParentTopic = (
    topic: TopicType,
    tempTopicTreeData: TopicType[]
): boolean => {
    let path = [];  // 保存路径信息

    // 通过深度优先搜索，找出目标节点的路径
    function dfs(node: TopicType[], idPath: string[]) {
        for (let i = 0; i < node.length; i++) {
            idPath.push(node[i].id);
            if (node[i].id === topic.id) {
                path = idPath.slice();
                return true;
            } else if (node[i].children && node[i].children.length) {
                if (dfs(node[i].children, idPath)) return true;
            }
            idPath.pop();  // 回溯
        }
        return false;
    }
    dfs(tempTopicTreeData, []);
    // 从路径中获取父节点和当前节点的id
    let currentNodeId = path.pop();
    let parentNodeId = path.pop();

    // 找到父节点
    let parentNode = null;
    dfs(tempTopicTreeData, []);

    function findParentNode(node, id) {
        for (let i = 0; i < node.length; i++) {
            if (node[i].id === id) {
                parentNode = node[i];
                return true;
            } else if (node[i].children && node[i].children.length) {
                if (findParentNode(node[i].children, id)) return true;
            }
        }
        return false;
    }
    findParentNode(tempTopicTreeData, parentNodeId);
    return parentNode && parentNode.children[parentNode.children.length - 1].id === currentNodeId;
}


const generateSystemChapter = (
    topic: TopicType,
    _tempTopicTreeData: TopicType[],
    topicTitleTagStatusConfig: TopicTitleTagStatusConfig,
    newComDocInstance: DocInstance,
    newComDocConfig: DocConfig,
    topicWordParagraphList: WordParagraphBlock[],
    mainContentsOfThePlanningActive: boolean,
    planningGoalActive: boolean,
    initDocInstance?: boolean  //是否是初始化时才执行
): {
    newTopic: TopicType,
    newTopicWordParagraphList: WordParagraphBlock[],
    _mainContentsOfThePlanningActive: boolean,
    _planningGoalActive: boolean
} => {
    const {
        planBasisList
    } = newComDocConfig;
    let {
        protectlandBaseInfo: {
            protectlandExtraInfo
        }
    } = newComDocInstance;
    if (isEmpty(protectlandExtraInfo)) {
        protectlandExtraInfo = {
            projectSubTableList: defaultProjectSubTableList,
            //@ts-ignore
            supplementaryInformation: {},
            //@ts-ignore
            protectedNaturalEnvironment: {}
        }
    }
    const {
        projectSubTableList = defaultProjectSubTableList,
        supplementaryInformation,
        protectedNaturalEnvironment
    } = protectlandExtraInfo;
    //开始生成其他章节文本
    /*************** start **************/
    if (topic.topicName == '规划主要建设内容') {
        mainContentsOfThePlanningActive = true;
    }
    /****************** 自动生成开始-规划主要建设内容 ***************/
    if (mainContentsOfThePlanningActive) {
        const tempWordParagraph = generateMainContentsOfThePlanningChapter(
            topic,
            _tempTopicTreeData,
            topicTitleTagStatusConfig,
            newComDocInstance,
            newComDocConfig
        );
        if (tempWordParagraph.length) {
            tempWordParagraph.unshift(topicWordParagraphList[0]);
            topicWordParagraphList = tempWordParagraph;
        }
        mainContentsOfThePlanningActive = false;
    }
    if (topic.topicName == '投资计划安排') {
        const tempWordParagraph = generateInvestmentArrangementChapter(
            topic,
            _tempTopicTreeData,
            topicTitleTagStatusConfig,
            newComDocInstance,
            newComDocConfig,
        );
        if (tempWordParagraph.length) {
            tempWordParagraph.unshift(topicWordParagraphList[0]);
            topicWordParagraphList = tempWordParagraph;
        }
    }
    if (topic.topicName == '规划投资') {
        const {
            paragraphTextList,
        } = getInvestmentArrangementContent(
            topic,
            newComDocInstance,
            newComDocConfig,
            false,
        );
        const tempWordParagraph: WordParagraphBlock[] = [];
        if (paragraphTextList.length) {
            paragraphTextList.forEach((text, index) => {
                tempWordParagraph.push(generateWordParagraphByPlainText(topic, text))
            })
        }
        if (tempWordParagraph.length) {
            tempWordParagraph.unshift(topicWordParagraphList[0]);
            topicWordParagraphList = tempWordParagraph;
        }
    }
    const tempWordParagraph = generatePlanningGoalChapter(
        topic,
        _tempTopicTreeData,
        topicTitleTagStatusConfig,
        newComDocInstance
    );
    if (tempWordParagraph.length) {
        tempWordParagraph.unshift(topicWordParagraphList[0]);
        topicWordParagraphList = tempWordParagraph;
    }
    // }
    /*************** end **************/
    /*************** start **************/
    if (topic.topicName == '重点建设工程' && topic.topicLevel == '1') {
        planningGoalActive = false;
    }
    if (topic.topicName == '存在问题与对策') {
        const tempWordParagraph = generateProtectlandProblemChapter(
            topic,
            _tempTopicTreeData,
            topicTitleTagStatusConfig,
            newComDocInstance
        );
        if (tempWordParagraph.length) {
            topicWordParagraphList = topicWordParagraphList.concat(tempWordParagraph)
        }
    }
    else if (topic.topicName == '重点工程' && topic.topicLevel === '1') {
        const tempWordParagraph = generateonKeyProjectsChapter(
            topic,
            _tempTopicTreeData,
            topicTitleTagStatusConfig,
            newComDocInstance,
            newComDocConfig
        );
        if (tempWordParagraph.length) {
            tempWordParagraph.unshift(topicWordParagraphList[0]);
            topicWordParagraphList = tempWordParagraph;
        }
    }
    //开始处理规划依据
    else if (topic.topicName == '规划依据' && planBasisList && planBasisList.length) {
        let planBasisGroupList: PlanningBasisGroupType[] = [];
        planBasisList.forEach(ele => {
            let findIndex = -1;
            planBasisGroupList.forEach((planBasisGroup, index) => {
                if (planBasisGroup.basisType == ele.basisType) {
                    findIndex = index;
                }
            })
            if (findIndex > -1) {
                planBasisGroupList[findIndex].planningBasisList.push(ele);
            } else {
                planBasisGroupList.push({
                    basisType: ele.basisType,
                    planningBasisList: [ele]
                })
            }
        })
        let tempTopicWordParagraphList = [topic.wordParagraphList[0]];
        planBasisGroupList.forEach((planBasisGroup, planBasisGroupindex) => {
            tempTopicWordParagraphList.push(generateWordParagraphByPlainText(topic, `${topic.serialNumber}.${planBasisGroupindex + 1} ${planBasisGroup.basisType}`));
            planBasisGroup.planningBasisList.forEach((planBasis, planBasisIndex) => {
                tempTopicWordParagraphList.push(generateWordParagraphByPlainText(topic, `（${planBasisIndex + 1}）${planBasis.basisName}`));
            })
        })
        topicWordParagraphList = [...tempTopicWordParagraphList];
        topic.wordParagraphList = [...tempTopicWordParagraphList];
    }
    if (initDocInstance) {
        if (topic.topicName === '地理位置及范围') {
            if (supplementaryInformation && supplementaryInformation.geographicalLocationText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.geographicalLocationText))
            }
            if (supplementaryInformation && supplementaryInformation.rangeText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.rangeText))
            }
        }
        else if (topic.topicName == '地理位置') {
            if (supplementaryInformation && supplementaryInformation.geographicalLocationText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.geographicalLocationText))
            }
        }
        else if (topic.topicName == '范围') {
            if (supplementaryInformation && supplementaryInformation.rangeText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.rangeText))
            }
        }
        else if (topic.topicName == '历史沿革') {
            if (supplementaryInformation && supplementaryInformation.historicalEvolutionText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.historicalEvolutionText))
            }
        }
        else if (topic.topicName == '法律地位') {
            if (supplementaryInformation && supplementaryInformation.legalStatusText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.legalStatusText))
            }
        }
        else if (topic.topicName == '主要保护对象') {
            if (supplementaryInformation && supplementaryInformation.mainProtectionObjecText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.mainProtectionObjecText))
            }
        }
        else if (topic.topicName == '行政区域') {
            if (supplementaryInformation && supplementaryInformation.administrativeDivisionText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.administrativeDivisionText))
            }
        }
        else if (topic.topicName == '土地权属') {
            if (supplementaryInformation && supplementaryInformation.landOwnershipText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.landOwnershipText))
            }
        }
        else if (topic.topicName == '地质地貌') {
            if (supplementaryInformation.geologyAndGeomorphologyText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.geologyAndGeomorphologyText))
            }
        }
        else if (topic.topicName == '气候') {
            if (supplementaryInformation && supplementaryInformation.climateText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.climateText))
            }
        }
        else if (topic.topicName == '水文') {
            if (supplementaryInformation && supplementaryInformation.hydrologyText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.hydrologyText))
            }
        }
        else if (topic.topicName == '土壤') {
            if (supplementaryInformation && supplementaryInformation.soilText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.soilText))
            }
        }
        else if (topic.topicName == '植被') {
            if (supplementaryInformation && supplementaryInformation.vegetationText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.vegetationText))
            }
        }
        else if (topic.topicName == '真菌') {
            if (supplementaryInformation && supplementaryInformation.fungusText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.fungusText))
            }
        }
        else if (topic.topicName == '景观资源') {
            if (supplementaryInformation && supplementaryInformation.landscapeResourcesText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.landscapeResourcesText))
            }
        }
        else if (topic.topicName == '自然灾害') {
            if (supplementaryInformation && supplementaryInformation.naturalDisasterText) {
                topicWordParagraphList.push(generateWordParagraphByPlainText(topic, supplementaryInformation.naturalDisasterText))
            }
        }
    }

    /**************** end ****************/
    /****************** 自动生成结束 ***************/
    return {
        newTopic: topic,
        newTopicWordParagraphList: topicWordParagraphList,
        _mainContentsOfThePlanningActive: mainContentsOfThePlanningActive,
        _planningGoalActive: planningGoalActive
    };
}

/**
 * 初始化文档状态
 * @param newTopicList 
 * @param newComDocInstance 
 * @returns 
 */
const initializeWordConfiguration = (
    newTopicList: TopicType[],
    newComDocInstance: DocInstance,
    newComDocConfig: DocConfig
): TopicType[] => {
    let _tempTopicList = newTopicList;
    const _tempTopicTreeData = deepCopy(generateTreeData(addTreePropertyForList(_tempTopicList)));
    let serialNumberList = [];
    let nextEntityKey = 0;
    let times = 0;
    let topicTitleTagStatusConfig: TopicTitleTagStatusConfig = {
        PlanningYears: false,
        EcologicalBenefitAnalysis: false,
        SocialBenefitAnalysis: false,
        SubSocialBenefitAnalysis: false,
        EconomicBenefitAnalysis: false,
        EnvironmentalCapacityAnalysis: false,
        OverallGoal: false,
        ShortTermGoal: false,
        MediumAndLongTermGoals: false,
        MainProject: false,
        ExistingProblems: false,
        MainContentsOfPlanning: false,
        InvestmentPlan: false,
        PlanningInvestment: false,
    }
    let mainContentsOfThePlanningActive = false;  //规划主要建设内容
    let planningGoalActive = false;               //规划目标
    let keyConstructionProjectActive = false;     //重点建设工程
    dfsRecursive(_tempTopicTreeData, (topic: TopicType, level: number) => {
        times++;
        if (topic.topicName == '草原植被恢复') {
        }
        if (serialNumberList.length > level) {
            serialNumberList = serialNumberList.splice(0, level + 1)
            serialNumberList[serialNumberList.length - 1]++;
        } else if (serialNumberList.length == level) {
            if (isEmpty(serialNumberList[level])) {
                serialNumberList[level] = 1;
            } else {
                serialNumberList[level]++;
            }
        } else {
            serialNumberList.push(1)
        }
        const serialNumber = serialNumberList.join('.');
        //初始化的标题序号
        topic.serialNumber = serialNumber;
        //当前节点下的文本段落列表
        let topicWordParagraphList: WordParagraphBlock[] = [];
        //第二步：生成此文本大纲附带的的背景文本
        if (topic.topicType == 'text') {
            //第一步：生成大纲标题
            const titleWordParagraph = getWordParagraphTitle(topic, []);
            topicWordParagraphList.push(titleWordParagraph);
            // 开始处理特定锚点
            if (topic.topicName == '规划期限') {
                //标记为规划期限
                topic.topicTag = 'PlanningYears';
                const planningYearsParagraphText = generatePlanningYearsTopic(topic, newComDocInstance);
                if (!isEmpty(planningYearsParagraphText)) {
                    topicWordParagraphList.push({
                        textTopicId: topic.id,
                        blockId: generateBlockId(),
                        type: 'text',
                        text: planningYearsParagraphText,
                        paragraphType: 'topic_title',
                        paragraphStyle: 'normal_paragraph',
                        inlineStyleRanges: []
                    })
                }
            } else if (topic.topicName == '生态效益') {
                //标记为生态效益分析
                topic.topicTag = 'EcologicalBenefitAnalysis';
            } else if (topic.topicName == '社会效益') {
                //标记为社会效益分析
                topic.topicTag = 'SocialBenefitAnalysis';
            } else if (topic.topicName == '经济效益') {
                //标记为生态效益分析
                topic.topicTag = 'EconomicBenefitAnalysis';
            } else if (topic.topicName == '环境容量分析') {
                topic.topicTag = 'EnvironmentalCapacityAnalysis';
            }
            //处理内置背景文本
            let backgroundParagraphList = [];
            if (!isEmpty(topic.backgroundParagraph1)) {
                backgroundParagraphList.push(topic.backgroundParagraph1)
            }
            if (!isEmpty(topic.backgroundParagraph2)) {
                backgroundParagraphList.push(topic.backgroundParagraph2)
            }
            if (!isEmpty(topic.backgroundParagraph3)) {
                backgroundParagraphList.push(topic.backgroundParagraph3)
            }
            if (!isEmpty(topic.backgroundParagraph4)) {
                backgroundParagraphList.push(topic.backgroundParagraph4)
            }
            if (backgroundParagraphList.length) {
                //随机抽取背景文本
                let currentBackgroundParagraph = lotteryStringList(backgroundParagraphList);
                let currentInUseBackgroundParagraphIndex = -1;
                //找到随机抽取的背景文本是哪个配置
                for (let i = 0; i < backgroundParagraphList.length; i++) {
                    if (backgroundParagraphList[i] == currentBackgroundParagraph) {
                        currentInUseBackgroundParagraphIndex = i;
                        break;
                    }
                }
                //替换当前规划信息
                currentBackgroundParagraph = replaceDocInfo(currentBackgroundParagraph, newComDocInstance);
                //标记当前随机使用的是哪个背景文本
                topic.currentInUseBackgroundParagraphIndex = currentInUseBackgroundParagraphIndex;
                //根据换行符分割背景文本
                const backgroundParagraphSliceList = currentBackgroundParagraph.split(/[(\r\n)\r\n]+/);
                // if (currentBackgroundParagraph.includes('生物能有效去')) {
                // }
                backgroundParagraphSliceList.forEach((backgroundParagraph, index) => {
                    //背景文本高亮检查 #高亮文本#
                    const paragraphTextSliceList = maptchSplitHighLightTextSlice(backgroundParagraph);
                    if (paragraphTextSliceList.length > 1) {
                        const backgroundParagraphWithHighLight = createContentBlockByInlineRanges(
                            paragraphTextSliceList,
                            'title_paragraph_6',
                            topic.id,
                        )
                        topicWordParagraphList.push({
                            textTopicId: topic.id,
                            blockId: generateBlockId(),
                            type: 'text',
                            text: backgroundParagraphWithHighLight.text,
                            paragraphType: 'default_background_paragraph',
                            paragraphStyle: 'normal_paragraph',
                            inlineStyleRanges: backgroundParagraphWithHighLight.inlineStyleRanges
                        })
                    } else {
                        topicWordParagraphList.push({
                            textTopicId: topic.id,
                            blockId: generateBlockId(),
                            type: 'text',
                            text: backgroundParagraph,
                            paragraphType: 'default_background_paragraph',
                            paragraphStyle: 'normal_paragraph',
                            inlineStyleRanges: []
                        })
                    }
                })
            }
            const {
                newTopic,
                newTopicWordParagraphList,
                _mainContentsOfThePlanningActive,
                _planningGoalActive,
            } = generateSystemChapter(
                topic,
                _tempTopicTreeData,
                topicTitleTagStatusConfig,
                newComDocInstance,
                newComDocConfig,
                topicWordParagraphList,
                mainContentsOfThePlanningActive,
                planningGoalActive,
                true
            )
            topic = newTopic;
            topicWordParagraphList = newTopicWordParagraphList;
            mainContentsOfThePlanningActive = _mainContentsOfThePlanningActive;
            planningGoalActive = _planningGoalActive;
            //筛选出大纲下的子节点
            let childrenDeviceTopicList: TopicType[] = [];
            topic.childrenDeviceTopicListLength = 0;
            if (topic.children && topic.children.length) {
                childrenDeviceTopicList = topic.children.filter(_topic => {
                    // return _topic.topicType == 'device';
                    return _topic.topicType == 'device' && _topic.checked;
                })
                topic.childrenDeviceTopicListLength = childrenDeviceTopicList.length;
                if (childrenDeviceTopicList.length) {
                    topic.childrenDeviceTopicListLength = childrenDeviceTopicList.length;
                    const {
                        deviceParagraphBlockList,
                        newNextEntityKey
                    } = getDeviceParagraphBlockList(topic, childrenDeviceTopicList, nextEntityKey, newComDocInstance, 'initializeWordConfiguration');
                    if (deviceParagraphBlockList && deviceParagraphBlockList.length) {
                        // deviceParagraphBlockList.forEach(deviceParagraphBlock => {
                        //     topicWordParagraphList.push(deviceParagraphBlock)
                        // })
                        topicWordParagraphList = topicWordParagraphList.concat(deviceParagraphBlockList);
                        nextEntityKey = newNextEntityKey;
                    } else {
                    }
                }
            }
            topic.wordParagraphList = [...topicWordParagraphList];
        }
    })
    _tempTopicList = tree2List(_tempTopicTreeData);
    return _tempTopicList;
}


/**
 * 
 * @param blockKey 
 * @returns 
 */
const getEditorBlockParagraphTypeByBlockKey = (blockKey: string): EditorBlockParagraphType => {
    if (!blockKey.includes('_')) {
        return 'TextTopic';
    } else if (blockKey.includes('custom_background_paragraph')) {
        return 'TextTopicCustomBackgroundParagraph';
    } else if (blockKey.includes('_background_paragraph')) {
        return 'TextTopicBackgroundParagraph';
    } else if (blockKey.includes('_device_paragraph')) {
        return 'TextTopicDeviceDescriptionParagraph';
    }
}

/**
 * 
 * @param block 
 * @returns 
 */
const getEditorBlockParagraphTypeByContentBlock = (block: ContentBlock): WordParagraphType => {
    const blockData = block.getData();
    const wordParagraphBlock: WordParagraphBlock = blockData.get('wordParagraph');
    if (!wordParagraphBlock) {
        return null;
    }
    return wordParagraphBlock.paragraphType;
}

const replaceBlockSelectionText = () => {

}

/**
 * 
 * @param editorState 
 * @param blockKey 
 * @param newText 
 * @returns EditorState
 */
const replaceBlockAllTextV1 = (editorState: EditorState, blockKey: string, newText: string): EditorState => {
    const content = editorState.getCurrentContent();
    const block = content.getBlockForKey(blockKey);

    // 创建一个全新的选择范围，覆盖整个block
    const targetRange = new SelectionState({
        anchorKey: blockKey,
        anchorOffset: 0,
        focusKey: blockKey,
        focusOffset: block.getLength(),
    });

    // 使用Modifier.replaceText替换选中的文本
    const newContent = Modifier.replaceText(
        content,
        targetRange,
        newText
    );

    // 使用EditorState.push将新的content应用到editorState
    const newEditorState = EditorState.push(
        editorState,
        newContent,
        'change-block-data'
    );

    // 保持光标在原来的位置
    return EditorState.forceSelection(newEditorState, editorState.getSelection());
}

/**
 * 
 * @param editorState 
 * @param blockKey 
 * @param newText 
 * @returns 
 */
const replaceBlockAllTextV2 = (editorState, blockKey, newText) => {
    const oldContent = editorState.getCurrentContent();
    const blockArray = oldContent.getBlocksAsArray();
    const blockIndex = blockArray.findIndex(block => block.getKey() === blockKey);

    if (blockIndex < 0) {
        // Block not found
        return editorState;
    }

    const oldBlock = blockArray[blockIndex];

    // 创建新的 ContentBlock
    const newBlock = new ContentBlock({
        key: blockKey,
        type: oldBlock.getType(),
        text: newText,
        characterList: List(Array(newText.length).fill(CharacterMetadata.create())), // Empty formatting
    });

    // Replace old block with new block in the array
    blockArray[blockIndex] = newBlock;

    // 创建新的 ContentState
    const newContent = ContentState.createFromBlockArray(blockArray);

    // 将新的 contentState 应用到 editorState
    const newEditorState = EditorState.push(editorState, newContent, 'insert-characters');

    return newEditorState;
}

/**
 * 
 * @param editorState 
 * @param newBlockDataList 
 * @returns 
 */
const replaceBlockData = (
    editorState: EditorState,
    newBlockDataList: DraftBlockData[],
    specialTextDecorator: DraftDecoratorType,
    tempComDocInstance: DocInstance,
    tempComDocConfig: DocConfig
): EditorState => {
    const {
        rawContent,
        updatedComDocInstance
    } = getInitializedRawContent(tempComDocInstance, tempComDocConfig)
    // let rawContent = convertToRaw(editorState.getCurrentContent());
    // newBlockDataList = [newBlockDataList[1]];
    newBlockDataList.forEach(newBlockData => {
        const blockKey = newBlockData.key;

        const blockIndex = rawContent.blocks.findIndex(block => block.key === blockKey);

        if (blockIndex >= 0) {
            //@ts-ignore
            rawContent.blocks[blockIndex] = newBlockData;
            // delete rawContent.blocks[blockIndex];
        }

    });
    // Create a new ContentState and push to the editor state for each block
    const newContentState = convertFromRaw(deepCopy(rawContent));
    const refreshEditorState = EditorState.createWithContent(newContentState, specialTextDecorator);
    const updatedSelection = editorState.getSelection();
    const forceUpdatedEditorState = EditorState.forceSelection(refreshEditorState, updatedSelection);
    return forceUpdatedEditorState;

    // let rawContent = convertToRaw(currentEditorState.getCurrentContent());

    // newBlockDataList.forEach(newBlockData => {
    //     const blockKey = newBlockData.key;

    //     const blockIndex = rawContent.blocks.findIndex(block => block.key === blockKey);

    //     if (blockIndex >= 0) {
    //         //@ts-ignore
    //         rawContent.blocks[blockIndex] = deepCopy(newBlockData);
    //     }

    //     // Create a new ContentState and push to the editor state for each block
    //     const newContent = convertFromRaw(rawContent);
    //     currentEditorState = EditorState.push(editorState, newContent, 'change-block-data');
    // });

    // return currentEditorState;
}

interface EcologincalBenefitParams {
    sign?: number,
    AT?: number,
    FP?: number,
    HP?: number,
    GP?: number,
    WP?: number,
    CP?: number,
    WH?: boolean,
    CO?: boolean,
    CR?: boolean,
    AC?: boolean,
    WC?: boolean,
    SC?: boolean,
    BD?: boolean,
    PN?: boolean,
}

/**
 * 
 * @param sign 小数点保留位数
 * @param AT 用户输入的保护地总面积, 单位：公顷；
 * @param FP 用户输入的保护地森林的面积比例，范围0至100，默认值0，当FP=0时，结果不输出林地提供的生态服务；
 * @param HP 用户输入的保护地灌丛的面积比例，范围0至100，默认值0，当HP=0时，结果不输出灌丛提供的生态服务；
 * @param GP 用户输入的保护地草地的面积比例，范围0至100，默认值0，当GP=0时，结果不输出草地提供的生态服务；
 * @param WP 用户输入的保护地湿地和水域的面积比例，范围0至100，默认值0，当WP=0时，结果不输出湿地和水域提供的生态服务；
 * @param CP 用户输入的保护地耕地的面积比例，范围0至100，默认值0，当CP=0时，结果不输出耕地提供的生态服务；
 * @param WH 逻辑判断参数，WH = T （Ture）表示计算水源涵养服务价值（默认设置）；WH = F （False）表示不计算；
 * @param CO 逻辑判断参数，CO = T （Ture）表示计算固碳释氧服务价值（默认设置）；CO = F （False）表示不计算；
 * @param CR 逻辑判断参数，CR = T （Ture）表示计算气候调节服务价值（默认设置）；CR = F （False）表示不计算；
 * @param AC 逻辑判断参数，AC = T （Ture）表示计算空气净化服务价值（默认设置）；AC = F （False）表示不计算；
 * @param WC 逻辑判断参数，WC = T （Ture）表示计算水质净化服务价值（默认设置）；WC = F （False）表示不计算；
 * @param SC 逻辑判断参数，SC = T （Ture）表示计算固土保肥服务价值（默认设置）；SC = F （False）表示不计算；
 * @param BD 逻辑判断参数，BD = T （Ture）表示计算生物多样性服务价值（默认设置）；BD= F （False）表示不计算；
 * @param PN 逻辑判断参数，NP = T （Ture）表示计算维持养分循环服务价值（默认设置）；NP= F （False）表示不计算；
 */
const generateEcologicalBenefit = (params: EcologincalBenefitParams): number[][] => {
    const {
        sign = 3,
        AT = 0,
        FP = 0,
        HP = 0,
        GP = 0,
        WP = 0,
        CP = 0,
        WH = true,
        CO = true,
        CR = true,
        AC = true,
        WC = true,
        SC = true,
        BD = true,
        PN = true,
    } = params;
    let dwh = [2.46351267, 1.51146405, 0.87560676, 3.62751372, 0.09381501];
    let dco = [3.23835516, 1.23696828, 1.2161205, 1.0076427, 0.15983298];
    let dcr = [2.45656341, 1.57400739, 1.23696828, 3.82904226, 0.14593446];
    let dac = [1.50104016, 1.11535623, 0.5211945, 0.83738583, 0.30576744];
    let dwc = [0.94509936, 0.53509302, 0.45865116, 2.9186892, 0.04169556];
    let dsc = [2.43919026, 2.30715432, 1.19527272, 0.10076427, 0.35788689];
    let dpn = [0.0694926, 0.05211945, 0.04169556, 0.06254334, 0.05211945];
    let dbd = [2.60944713, 1.35163107, 1.34468181, 2.32452747, 0.05906871];

    const AF = AT * FP / 100;
    const AH = AT * HP / 100;
    const AG = AT * GP / 100;
    const AW = AT * WP / 100;
    const CA = AT * CP / 100;

    /**
     * 
     * @param num 
     * @param decimalPlaces 
     * @returns 
     */
    function _roundNumber(num, decimalPlaces) {
        let multiplier = Math.pow(10, decimalPlaces);
        return Math.round(num * multiplier) / multiplier;
    }

    function generateEcologicalBenefitForColumn(valueList: number[], index: number): number[] {
        let tempValueList = valueList;
        let BASE_VALUE = AF;
        switch (index) {
            case 0:
                BASE_VALUE = AF;
                break;
            case 1:
                BASE_VALUE = AH;
                break;
            case 2:
                BASE_VALUE = AG;
                break;
            case 3:
                BASE_VALUE = AW;
                break;
            case 4:
                BASE_VALUE = CA;
                break;
            default:
                break;
        }
        if (WH) {
            tempValueList = tempValueList.concat([dwh[index] * BASE_VALUE, dwh[index]]);
        }
        if (CO) {
            tempValueList = tempValueList.concat([dco[index] * BASE_VALUE, dco[index]]);
        }
        if (CR) {
            tempValueList = tempValueList.concat([dcr[index] * BASE_VALUE, dcr[index]]);
        }
        if (AC) {
            tempValueList = tempValueList.concat([dac[index] * BASE_VALUE, dac[index]]);
        }
        if (WC) {
            tempValueList = tempValueList.concat([dwc[index] * BASE_VALUE, dwc[index]]);
        }
        if (SC) {
            tempValueList = tempValueList.concat([dsc[index] * BASE_VALUE, dsc[index]]);
        }
        if (PN) {
            tempValueList = tempValueList.concat([dpn[index] * BASE_VALUE, dpn[index]]);
        }
        if (BD) {
            tempValueList = tempValueList.concat([dbd[index] * BASE_VALUE, dbd[index]]);
        }
        let sumOddIndexElements = tempValueList
            .filter((_, index) => index % 2 === 0)
            .reduce((acc, curr) => acc + curr, 0);
        let tf1 = [sumOddIndexElements, sumOddIndexElements / BASE_VALUE];
        let tf1AndTempValueList = tf1.concat(tempValueList);
        let roundedValueList = tf1AndTempValueList.map(num => _roundNumber(num, sign));
        return roundedValueList;
    }

    function swapOddEvenPositions(arr) {
        for (let i = 0; i < arr.length - 1; i += 2) {
            let temp = arr[i];
            arr[i] = arr[i + 1];
            arr[i + 1] = temp;
        }
        return arr;
    }

    let totalValueListGroup = [];

    //如果保护地森林的面积比例不为0
    if (FP != 0) {
        let forestList = [];
        const roundedForestList = generateEcologicalBenefitForColumn(forestList, 0);
        totalValueListGroup.push(roundedForestList);
    }

    //如果保护地灌丛的面积比例不为0
    if (HP != 0) {
        let shrubList = [];
        const roundedShrubList = generateEcologicalBenefitForColumn(shrubList, 1);
        totalValueListGroup.push(roundedShrubList);
    }

    //如果保护地草地的面积比例不为0
    if (GP != 0) {
        let grassList = [];
        const roundedGrassList = generateEcologicalBenefitForColumn(grassList, 2);
        totalValueListGroup.push(roundedGrassList);
    }

    //如果保护地湿地和水域的面积比例不为0
    if (WP != 0) {
        let wetlandList = [];
        const roundedWetlandList = generateEcologicalBenefitForColumn(wetlandList, 3);
        totalValueListGroup.push(roundedWetlandList);
    }

    //如果保护地耕地的面积比例不为0
    if (CP != 0) {
        let cultivatedList = [];
        const roundedCultivatedList = generateEcologicalBenefitForColumn(cultivatedList, 4);
        totalValueListGroup.push(roundedCultivatedList);
    }

    let totalValueColumn = [];
    let _totalValueListGroup = totalValueListGroup[0].map(_ => []);

    for (let i = 0; i < totalValueListGroup.length; i++) {
        totalValueListGroup[i].forEach((value, index) => {
            _totalValueListGroup[index][i] = value;
        })
    }
    totalValueListGroup = [..._totalValueListGroup];
    let T1 = totalValueListGroup.map(row => _.sum(row));
    // 选取 T1 中的奇数索引的元素，结果保存到 T2 中
    let T2 = T1.filter((value, index) => index % 2 === 0);

    // 将 T2 中的元素除以 AT（保护地总面积），结果保存到 T3 中
    let T3 = T2.map(value => value / AT);

    // 创建一个全为 0 的新数组 保护地整体，长度等于 F0 的行数
    totalValueColumn = new Array(totalValueListGroup.length).fill(0);

    // 将 T3 中的值赋给 保护地整体 数组的偶数索引的元素
    T3.forEach((value, index) => totalValueColumn[index * 2] = value);

    // 将 T2 中的值赋给 保护地整体 数组的奇数索引的元素
    T2.forEach((value, index) => totalValueColumn[index * 2 + 1] = value);

    // 对 保护地整体 数组中的每个元素进行四舍五入，小数点后保留 sign 位数

    totalValueColumn = totalValueColumn.map(value => Number(value.toFixed(sign)));

    // 将 保护地整体 数组添加到 F0 数组的右边，结果保存到新的数组 F1 中
    let F1 = totalValueListGroup.map((row, index) => [...row, totalValueColumn[index]]);
    let _totalValueColumn = swapOddEvenPositions(totalValueColumn);
    _totalValueColumn.forEach((_totalValue, _index) => {
        totalValueListGroup[_index].push(_totalValue)
    })
    return totalValueListGroup;
}


const createStyleRanges = (text, species: SpeciesInfoType[]) => {
    const inlineStyleRanges = [];
    const regex = /\((.*?)\)/g;
    let match;

    while ((match = regex.exec(text)) !== null) {
        const matchFound = species.some(item => item.canorical_me === match[1]);

        if (matchFound) {
            inlineStyleRanges.push({
                offset: match.index + 1,
                length: match[1].length,
                style: 'ITALIC',
            });
            inlineStyleRanges.push({
                offset: match.index + 1,
                length: match[1].length,
                style: 'TimesNewRoman',
            });
        }
    }
    return inlineStyleRanges;
}

const createStyleRangesV2 = (text, species: SpeciesInfoType[]) => {
    const inlineStyleRanges = [];
    const regex = /\((.*?)\)/g; // 正则表达式，匹配括号内的内容
    let match;

    // 使用exec方法循环查找所有匹配项
    while ((match = regex.exec(text)) !== null) {
        // 拆分括号内的内容为属名和种名
        const [genus, speciesName] = match[1].split(' ');

        // 检查括号内的属名或种名是否在species数组中的canorical_me属性值中
        const genusFound = species.some(item => item.canorical_me.startsWith(genus));
        const speciesFound = species.some(item => item.canorical_me.endsWith(speciesName));

        // 如果找到匹配，那么将此范围添加到inlineStyleRanges数组中
        if (genusFound || speciesFound) {
            inlineStyleRanges.push({
                offset: match.index + 1, // 加 1 是因为我们想从括号内的第一个字符开始，不包括左括号
                length: genus.length, // genus 包含括号内的属名
                style: 'ITALIC',
            });
            inlineStyleRanges.push({
                offset: match.index + 1, // 加 1 是因为我们想从括号内的第一个字符开始，不包括左括号
                length: genus.length, // genus 包含括号内的属名
                style: 'TimesNewRoman',
            });

            // 如果种名存在，则为种名添加样式
            if (speciesName) {
                inlineStyleRanges.push({
                    offset: match.index + 1 + genus.length + 1, // 加上属名长度和空格
                    length: speciesName.length,
                    style: 'ITALIC',
                });
                inlineStyleRanges.push({
                    offset: match.index + 1 + genus.length + 1, // 加上属名长度和空格
                    length: speciesName.length,
                    style: 'TimesNewRoman',
                });
            }
        }
    }
    return inlineStyleRanges;
};


/**
 * 填充拉丁名
 * @param text 
 * @param species 
 * @returns 
 */
const findSpeciesInText = (text: string, species: SpeciesInfoType[]): {
    replacedText: string
    inlineStyleRanges: DraftInlineStyle[]
} => {
    let replacedText = text;
    let inlineStyleRanges = [];
    species.sort((a, b) => b.species_c.length - a.species_c.length);

    species.forEach(item => {
        const regex = new RegExp(item.species_c, 'g');
        if (replacedText.includes(`(${item.canorical_me})`)) {
            return;
        }
        let match;
        let firstMatch = true;
        while ((match = regex.exec(replacedText)) !== null) {
            if (firstMatch) {
                replacedText = replacedText.substring(0, match.index) +
                    `${item.species_c}(${item.canorical_me})` +
                    replacedText.substring(match.index + match[0].length);
                firstMatch = false;
            }
        }
    });
    inlineStyleRanges = createStyleRanges(replacedText, species)
    inlineStyleRanges.sort((a, b) => a.offset - b.offset);

    return {
        replacedText,
        inlineStyleRanges
    };
};

// const updateTextAndStyles = (text: string, species: SpeciesInfoType[], inlineStyleRanges: DraftInlineStyle[]): {
//     newText: string,
//     newInlineStyleRanges: DraftInlineStyle[]
// } => {
//     const newText = fillLatinName(species, text);
//     const newInlineStyleRanges = createStyleRanges(newText, species);
//     return {
//         newText,
//         newInlineStyleRanges
//     };
// };

const findSpeciesInTextV2 = (
    text: string, speciesList: SpeciesInfoType[]
): {
    replacedText: string
    inlineStyleRanges: DraftInlineStyle[],
    newSpeciesList: SpeciesInfoType[]
} => {
    const speciesDict: Record<string, SpeciesInfoType> = {};
    const genusDict: Record<string, string> = {};
    const appearedSpecies: Record<string, boolean> = {};
    for (const species of speciesList) {
        speciesDict[species.species_c] = species;
    }

    const regex = new RegExp('(' + Object.keys(speciesDict).join("|") + ')', 'g');
    let filledText = text;
    let match;
    let newSpeciesList = [];
    speciesList.forEach(speciesItem => {
        if (!text.includes(speciesItem.species_c)) {
            newSpeciesList.push(speciesItem)
        }
    })
    while ((match = regex.exec(text)) !== null) {
        const speciesName = match[0];
        const speciesData = speciesDict[speciesName];

        if (speciesData && !appearedSpecies[speciesName]) {
            appearedSpecies[speciesName] = true;
            const genusName = speciesData.genus;
            const latinName = speciesData.canorical_me;

            if (genusDict[genusName]) {
                // If the genus has been seen before, abbreviate it
                const abbreviatedLatinName = latinName.replace(genusName, genusDict[genusName]);
                filledText = filledText.replace(speciesName, `${speciesName}(${abbreviatedLatinName})`);
            } else {
                // Otherwise, fill the full latin name
                genusDict[genusName] = `${genusName.charAt(0)}.`;
                filledText = filledText.replace(speciesName, `${speciesName}(${latinName})`);
            }
        }
    }
    const newInlineStyleRanges = createStyleRangesV2(filledText, speciesList);
    return {
        replacedText: filledText,
        inlineStyleRanges: newInlineStyleRanges,
        newSpeciesList
    };
}

const arraysAreEqual = (a, b) => {
    return a.length === b.length && a.every((val, index) => val === b[index]);
}

const getUniquenStringArray = (stringArray: string[]) => {
    let uniqueStringArray = stringArray.reduce((accumulator, item) => {
        if (!accumulator.includes(item)) {
            accumulator.push(item);
        }
        return accumulator;
    }, []);
    return uniqueStringArray;
}

const convertDraftModelToSliceModel = (text, inlineStyleRanges) => {

    // 创建一个数组来存储每个字符的样式
    let stylesAtEachIndex = new Array(text.length).fill(undefined).map(() => []);

    // 对于每个样式范围，将样式添加到适当的索引处
    inlineStyleRanges.forEach(range => {
        for (let i = range.offset; i < range.offset + range.length; i++) {
            stylesAtEachIndex[i].push(range.style);
        }
    });

    // 现在，遍历stylesAtEachIndex数组，合并相邻的具有相同样式的字符
    let output: WordParagraphBlockSlice[] = [];
    let currentStyles = stylesAtEachIndex[0];
    let currentStart = 0;

    for (let i = 1; i < stylesAtEachIndex.length; i++) {
        // 如果这个索引处的样式与上一个索引处的样式不同，那么将当前的切片添加到输出中，并开始一个新的切片
        if (!arraysAreEqual(currentStyles, stylesAtEachIndex[i])) {
            output.push({
                content: text.slice(currentStart, i),
                styleList: currentStyles
            });
            currentStart = i;
            currentStyles = stylesAtEachIndex[i];
        }
    }

    // 添加最后一个切片
    output.push({
        content: text.slice(currentStart),
        styleList: currentStyles
    });
    output.forEach(slice => {
        slice.styleList = getUniquenStringArray(slice.styleList)
    })
    return output;
}

const getInlineStyleRanges = (block: ContentBlock) => {
    const charList = block.getCharacterList();
    let ranges = [];
    let currentRange;

    charList.forEach((char, i) => {
        const styles = char.getStyle();

        if (!currentRange) {
            // 开始一个新的range
            currentRange = {
                offset: i,
                length: 1,
                styles: styles
            };
        } else if (styles.equals(currentRange.styles)) {
            // 如果styles没有改变，增加当前range的长度
            currentRange.length++;
        } else {
            // 否则，结束当前range并开始一个新的range
            ranges.push(currentRange);
            currentRange = {
                offset: i,
                length: 1,
                styles: styles
            };
        }
    });
    if (currentRange) {
        ranges.push(currentRange);
    }
    return ranges;
}

/**
 * 更新指定的 block。
 * 
 * @param editorState 当前的 EditorState
 * @param blockId 要更新的 block 的唯一标识符
 * @param newBlockContent 新的 block 内容
 * @return 更新后的 EditorState
 */
function updateSpecificBlock(editorState, blockId, newBlockContent) {
    const contentState = editorState.getCurrentContent();
    const blockMap = contentState.getBlockMap();

    const newBlockMap = blockMap.map(block => {
        if (block.getKey() === blockId) {
            return block.merge({
                text: newBlockContent,
            });
        }
        return block;
    });

    const newContentState = contentState.merge({
        blockMap: newBlockMap,
        selectionBefore: contentState.getSelectionBefore(),
        selectionAfter: contentState.getSelectionAfter()
    });

    return EditorState.push(editorState, newContentState, 'apply-entity');
}

const replaceLastCharWithPeriod = (text: string) => {
    if (text.length === 0) {
        return text; // 如果文本为空，直接返回
    }
    return text.substring(0, text.length - 1) + '。'; // 替换最后一个字符为句号
}

/**
 * 把excel的数据转化成tableData格式
 * @param excelCellDataList 
 * @param mergeBoundInfoList 
 * @returns 
 */
const convertExcelCellDataListToTableData = (
    excelCellDataList: ExcelCellData[],
    mergeBoundInfoList: TypeMergeCellBound[]
): {
    tableData: string[][],
    tableColSpanInfoList: ColSpanInfo[],
    tableRowSpanInfoList: RowSpanInfo[]
} => {
    let tableData: string[][] = [];
    let tableColSpanInfoList: ColSpanInfo[] = [];
    let tableRowSpanInfoList: RowSpanInfo[] = [];
    let maxOffsetY = 0;
    let maxOffsetX = 0;
    excelCellDataList.forEach((cellData, index) => {
        if (maxOffsetY <= cellData.r) {
            maxOffsetY = cellData.r;
        }
        if (maxOffsetX <= cellData.c) {
            maxOffsetX = cellData.c;
        }
    })
    for (let y = 0; y <= maxOffsetY; y++) {
        let rowList: string[] = [];
        for (let x = 0; x <= maxOffsetX; x++) {
            rowList.push("")
        }
        tableData.push(rowList);
    }
    excelCellDataList.forEach(cellData => {
        tableData[cellData.r][cellData.c] = cellData.m + '';
    })
    mergeBoundInfoList.forEach(mergedBoundInfo => {
        let colIndex = mergedBoundInfo.bounds[0][0];
        let rowIndex = mergedBoundInfo.bounds[0][1];
        let rowSpan = mergedBoundInfo.bounds[1][1] - mergedBoundInfo.bounds[0][1] + 1;
        let colSpan = mergedBoundInfo.bounds[1][0] - mergedBoundInfo.bounds[0][0] + 1;
        if (colSpan > 1) {
            tableColSpanInfoList.push({
                colIndex,
                rowIndex,
                colSpan: colSpan
            })
        }
        if (rowSpan > 1) {
            tableRowSpanInfoList.push({
                colIndex,
                rowIndex,
                rowSpan: rowSpan
            })
        }
    })
    let newTableData = [];
    tableData.forEach(row => {
        let tempRow = [];
        row.forEach(str => {
            if (isEmpty(str)) {
                tempRow.push('-');
            } else {
                tempRow.push(str + '-');
            }
        })
        tempRow.pop();
        newTableData.push(tempRow);
        
    })
    let result = {
        tableData: newTableData,
        tableColSpanInfoList: tableColSpanInfoList,
        tableRowSpanInfoList: tableRowSpanInfoList,
    }
    return result;
}


export {
    generateBlockId,
    createContentBlock,
    createContentBlockByInlineRanges,
    initializeWordConfiguration,
    getInitializedRawContent,
    preProcessComDocInstanceBeforeUpdate,
    updateEditorState,
    replaceDocInfo,
    replaceDeviveInfo,
    moveSelectionToEnd,
    generateDeviceParagraphSlice,
    lotteryStringList,
    maptchSplitHighLightTextSlice,
    getEntityText,
    checkIsParagraphTitle,
    getInlineStyleRangesForBlock,
    getDeviceParagraphSpecialTextEntities,
    getDeviceEntityTag,
    getDeviceTopicReplaceText,
    getTwoTextDiffLen,
    replaceTextByRange,
    getEditorBlockParagraphTypeByBlockKey,
    getEditorBlockParagraphTypeByContentBlock,
    replaceBlockAllTextV1,
    replaceBlockAllTextV2,
    replaceBlockData,
    generateEcologicalBenefit,
    findSpeciesInText,
    findSpeciesInTextV2,
    proteclandTypeOnlineData,
    getInlineStyleRanges,
    convertDraftModelToSliceModel,
    updateSpecificBlock,
    replaceLastCharWithPeriod,
    convertExcelCellDataListToTableData,
    deleteTableDataEmptyColumn,
    findCellValuColIndex,
    removeAndAdjustColumn,
    getDeviceParagraphBlockList
}

